[FileAccess] Return error codes from store_* methods.

This commit is contained in:
bruvzg 2023-06-15 21:21:43 +03:00 committed by Pāvels Nadtočajevs
parent 56a7dba10b
commit a4b17e7852
30 changed files with 279 additions and 138 deletions

View File

@ -34,8 +34,79 @@ Ref<FileAccess> FileAccess::_open_encrypted_bind_compat_98918(const String &p_pa
return open_encrypted(p_path, p_mode_flags, p_key, Vector<uint8_t>());
}
void FileAccess::_bind_compatibility_methods() {
ClassDB::bind_compatibility_static_method("FileAccess", D_METHOD("open_encrypted", "path", "mode_flags", "key"), &FileAccess::_open_encrypted_bind_compat_98918);
void FileAccess::store_8_bind_compat_78289(uint8_t p_dest) {
store_8(p_dest);
}
#endif // DISABLE_DEPRECATED
void FileAccess::store_16_bind_compat_78289(uint16_t p_dest) {
store_16(p_dest);
}
void FileAccess::store_32_bind_compat_78289(uint32_t p_dest) {
store_32(p_dest);
}
void FileAccess::store_64_bind_compat_78289(uint64_t p_dest) {
store_64(p_dest);
}
void FileAccess::store_buffer_bind_compat_78289(const Vector<uint8_t> &p_buffer) {
store_buffer(p_buffer);
}
void FileAccess::store_var_bind_compat_78289(const Variant &p_var, bool p_full_objects) {
store_var(p_var, p_full_objects);
}
void FileAccess::store_half_bind_compat_78289(float p_dest) {
store_half(p_dest);
}
void FileAccess::store_float_bind_compat_78289(float p_dest) {
store_float(p_dest);
}
void FileAccess::store_double_bind_compat_78289(double p_dest) {
store_double(p_dest);
}
void FileAccess::store_real_bind_compat_78289(real_t p_real) {
store_real(p_real);
}
void FileAccess::store_string_bind_compat_78289(const String &p_string) {
store_string(p_string);
}
void FileAccess::store_line_bind_compat_78289(const String &p_line) {
store_line(p_line);
}
void FileAccess::store_csv_line_bind_compat_78289(const Vector<String> &p_values, const String &p_delim) {
store_csv_line(p_values, p_delim);
}
void FileAccess::store_pascal_string_bind_compat_78289(const String &p_string) {
store_pascal_string(p_string);
}
void FileAccess::_bind_compatibility_methods() {
ClassDB::bind_compatibility_static_method("FileAccess", D_METHOD("open_encrypted", "path", "mode_flags", "key"), &FileAccess::_open_encrypted_bind_compat_98918);
ClassDB::bind_compatibility_method(D_METHOD("store_8", "value"), &FileAccess::store_8_bind_compat_78289);
ClassDB::bind_compatibility_method(D_METHOD("store_16", "value"), &FileAccess::store_16_bind_compat_78289);
ClassDB::bind_compatibility_method(D_METHOD("store_32", "value"), &FileAccess::store_32_bind_compat_78289);
ClassDB::bind_compatibility_method(D_METHOD("store_64", "value"), &FileAccess::store_64_bind_compat_78289);
ClassDB::bind_compatibility_method(D_METHOD("store_half", "value"), &FileAccess::store_half_bind_compat_78289);
ClassDB::bind_compatibility_method(D_METHOD("store_float", "value"), &FileAccess::store_float_bind_compat_78289);
ClassDB::bind_compatibility_method(D_METHOD("store_double", "value"), &FileAccess::store_double_bind_compat_78289);
ClassDB::bind_compatibility_method(D_METHOD("store_real", "value"), &FileAccess::store_real_bind_compat_78289);
ClassDB::bind_compatibility_method(D_METHOD("store_buffer", "buffer"), &FileAccess::store_buffer_bind_compat_78289);
ClassDB::bind_compatibility_method(D_METHOD("store_line", "line"), &FileAccess::store_line_bind_compat_78289);
ClassDB::bind_compatibility_method(D_METHOD("store_csv_line", "values", "delim"), &FileAccess::store_csv_line_bind_compat_78289, DEFVAL(","));
ClassDB::bind_compatibility_method(D_METHOD("store_string", "string"), &FileAccess::store_string_bind_compat_78289);
ClassDB::bind_compatibility_method(D_METHOD("store_var", "value", "full_objects"), &FileAccess::store_var_bind_compat_78289, DEFVAL(false));
ClassDB::bind_compatibility_method(D_METHOD("store_pascal_string", "string"), &FileAccess::store_pascal_string_bind_compat_78289);
}
#endif

View File

@ -495,56 +495,56 @@ String FileAccess::get_as_utf8_string(bool p_skip_cr) const {
return s;
}
void FileAccess::store_8(uint8_t p_dest) {
store_buffer(&p_dest, sizeof(uint8_t));
bool FileAccess::store_8(uint8_t p_dest) {
return store_buffer(&p_dest, sizeof(uint8_t));
}
void FileAccess::store_16(uint16_t p_dest) {
bool FileAccess::store_16(uint16_t p_dest) {
if (big_endian) {
p_dest = BSWAP16(p_dest);
}
store_buffer(reinterpret_cast<uint8_t *>(&p_dest), sizeof(uint16_t));
return store_buffer(reinterpret_cast<uint8_t *>(&p_dest), sizeof(uint16_t));
}
void FileAccess::store_32(uint32_t p_dest) {
bool FileAccess::store_32(uint32_t p_dest) {
if (big_endian) {
p_dest = BSWAP32(p_dest);
}
store_buffer(reinterpret_cast<uint8_t *>(&p_dest), sizeof(uint32_t));
return store_buffer(reinterpret_cast<uint8_t *>(&p_dest), sizeof(uint32_t));
}
void FileAccess::store_64(uint64_t p_dest) {
bool FileAccess::store_64(uint64_t p_dest) {
if (big_endian) {
p_dest = BSWAP64(p_dest);
}
store_buffer(reinterpret_cast<uint8_t *>(&p_dest), sizeof(uint64_t));
return store_buffer(reinterpret_cast<uint8_t *>(&p_dest), sizeof(uint64_t));
}
void FileAccess::store_real(real_t p_real) {
bool FileAccess::store_real(real_t p_real) {
if constexpr (sizeof(real_t) == 4) {
store_float(p_real);
return store_float(p_real);
} else {
store_double(p_real);
return store_double(p_real);
}
}
void FileAccess::store_half(float p_dest) {
store_16(Math::make_half_float(p_dest));
bool FileAccess::store_half(float p_dest) {
return store_16(Math::make_half_float(p_dest));
}
void FileAccess::store_float(float p_dest) {
bool FileAccess::store_float(float p_dest) {
MarshallFloat m;
m.f = p_dest;
store_32(m.i);
return store_32(m.i);
}
void FileAccess::store_double(double p_dest) {
bool FileAccess::store_double(double p_dest) {
MarshallDouble m;
m.d = p_dest;
store_64(m.l);
return store_64(m.l);
}
uint64_t FileAccess::get_modified_time(const String &p_file) {
@ -628,19 +628,18 @@ Error FileAccess::set_read_only_attribute(const String &p_file, bool p_ro) {
return err;
}
void FileAccess::store_string(const String &p_string) {
bool FileAccess::store_string(const String &p_string) {
if (p_string.length() == 0) {
return;
return true;
}
CharString cs = p_string.utf8();
store_buffer((uint8_t *)&cs[0], cs.length());
return store_buffer((uint8_t *)&cs[0], cs.length());
}
void FileAccess::store_pascal_string(const String &p_string) {
bool FileAccess::store_pascal_string(const String &p_string) {
CharString cs = p_string.utf8();
store_32(cs.length());
store_buffer((uint8_t *)&cs[0], cs.length());
return store_32(cs.length()) && store_buffer((uint8_t *)&cs[0], cs.length());
}
String FileAccess::get_pascal_string() {
@ -655,13 +654,12 @@ String FileAccess::get_pascal_string() {
return ret;
}
void FileAccess::store_line(const String &p_line) {
store_string(p_line);
store_8('\n');
bool FileAccess::store_line(const String &p_line) {
return store_string(p_line) && store_8('\n');
}
void FileAccess::store_csv_line(const Vector<String> &p_values, const String &p_delim) {
ERR_FAIL_COND(p_delim.length() != 1);
bool FileAccess::store_csv_line(const Vector<String> &p_values, const String &p_delim) {
ERR_FAIL_COND_V(p_delim.length() != 1, false);
String line = "";
int size = p_values.size();
@ -678,30 +676,43 @@ void FileAccess::store_csv_line(const Vector<String> &p_values, const String &p_
line += value;
}
store_line(line);
return store_line(line);
}
void FileAccess::store_buffer(const Vector<uint8_t> &p_buffer) {
bool FileAccess::store_buffer(const Vector<uint8_t> &p_buffer) {
uint64_t len = p_buffer.size();
if (len == 0) {
return true;
}
const uint8_t *r = p_buffer.ptr();
store_buffer(r, len);
return store_buffer(r, len);
}
void FileAccess::store_var(const Variant &p_var, bool p_full_objects) {
bool FileAccess::store_buffer(const uint8_t *p_src, uint64_t p_length) {
ERR_FAIL_COND_V(!p_src && p_length > 0, false);
for (uint64_t i = 0; i < p_length; i++) {
if (unlikely(!store_8(p_src[i]))) {
return false;
}
}
return true;
}
bool FileAccess::store_var(const Variant &p_var, bool p_full_objects) {
int len;
Error err = encode_variant(p_var, nullptr, len, p_full_objects);
ERR_FAIL_COND_MSG(err != OK, "Error when trying to encode Variant.");
ERR_FAIL_COND_V_MSG(err != OK, false, "Error when trying to encode Variant.");
Vector<uint8_t> buff;
buff.resize(len);
uint8_t *w = buff.ptrw();
err = encode_variant(p_var, &w[0], len, p_full_objects);
ERR_FAIL_COND_MSG(err != OK, "Error when trying to encode Variant.");
ERR_FAIL_COND_V_MSG(err != OK, false, "Error when trying to encode Variant.");
store_32(len);
store_buffer(buff);
return store_32(len) && store_buffer(buff);
}
Vector<uint8_t> FileAccess::get_file_as_bytes(const String &p_path, Error *r_error) {
@ -864,7 +875,7 @@ void FileAccess::_bind_methods() {
ClassDB::bind_method(D_METHOD("store_float", "value"), &FileAccess::store_float);
ClassDB::bind_method(D_METHOD("store_double", "value"), &FileAccess::store_double);
ClassDB::bind_method(D_METHOD("store_real", "value"), &FileAccess::store_real);
ClassDB::bind_method(D_METHOD("store_buffer", "buffer"), (void(FileAccess::*)(const Vector<uint8_t> &)) & FileAccess::store_buffer);
ClassDB::bind_method(D_METHOD("store_buffer", "buffer"), (bool(FileAccess::*)(const Vector<uint8_t> &)) & FileAccess::store_buffer);
ClassDB::bind_method(D_METHOD("store_line", "line"), &FileAccess::store_line);
ClassDB::bind_method(D_METHOD("store_csv_line", "values", "delim"), &FileAccess::store_csv_line, DEFVAL(","));
ClassDB::bind_method(D_METHOD("store_string", "string"), &FileAccess::store_string);

View File

@ -112,6 +112,21 @@ protected:
#ifndef DISABLE_DEPRECATED
static Ref<FileAccess> _open_encrypted_bind_compat_98918(const String &p_path, ModeFlags p_mode_flags, const Vector<uint8_t> &p_key);
void store_8_bind_compat_78289(uint8_t p_dest);
void store_16_bind_compat_78289(uint16_t p_dest);
void store_32_bind_compat_78289(uint32_t p_dest);
void store_64_bind_compat_78289(uint64_t p_dest);
void store_buffer_bind_compat_78289(const Vector<uint8_t> &p_buffer);
void store_var_bind_compat_78289(const Variant &p_var, bool p_full_objects = false);
void store_half_bind_compat_78289(float p_dest);
void store_float_bind_compat_78289(float p_dest);
void store_double_bind_compat_78289(double p_dest);
void store_real_bind_compat_78289(real_t p_real);
void store_string_bind_compat_78289(const String &p_string);
void store_line_bind_compat_78289(const String &p_line);
void store_csv_line_bind_compat_78289(const Vector<String> &p_values, const String &p_delim = ",");
void store_pascal_string_bind_compat_78289(const String &p_string);
static void _bind_compatibility_methods();
#endif
@ -164,6 +179,7 @@ public:
virtual String get_as_utf8_string(bool p_skip_cr = false) const;
/**
* Use this for files WRITTEN in _big_ endian machines (ie, amiga/mac)
* It's not about the current CPU type but file formats.
* This flag gets reset to `false` (little endian) on each open.
@ -175,27 +191,27 @@ public:
virtual Error resize(int64_t p_length) = 0;
virtual void flush() = 0;
virtual void store_8(uint8_t p_dest); ///< store a byte
virtual void store_16(uint16_t p_dest); ///< store 16 bits uint
virtual void store_32(uint32_t p_dest); ///< store 32 bits uint
virtual void store_64(uint64_t p_dest); ///< store 64 bits uint
virtual bool store_8(uint8_t p_dest); ///< store a byte
virtual bool store_16(uint16_t p_dest); ///< store 16 bits uint
virtual bool store_32(uint32_t p_dest); ///< store 32 bits uint
virtual bool store_64(uint64_t p_dest); ///< store 64 bits uint
virtual void store_half(float p_dest);
virtual void store_float(float p_dest);
virtual void store_double(double p_dest);
virtual void store_real(real_t p_real);
virtual bool store_half(float p_dest);
virtual bool store_float(float p_dest);
virtual bool store_double(double p_dest);
virtual bool store_real(real_t p_real);
virtual void store_string(const String &p_string);
virtual void store_line(const String &p_line);
virtual void store_csv_line(const Vector<String> &p_values, const String &p_delim = ",");
virtual bool store_string(const String &p_string);
virtual bool store_line(const String &p_line);
virtual bool store_csv_line(const Vector<String> &p_values, const String &p_delim = ",");
virtual void store_pascal_string(const String &p_string);
virtual bool store_pascal_string(const String &p_string);
virtual String get_pascal_string();
virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) = 0; ///< store an array of bytes, needs to be overwritten by children.
void store_buffer(const Vector<uint8_t> &p_buffer);
virtual bool store_buffer(const uint8_t *p_src, uint64_t p_length) = 0; ///< store an array of bytes, needs to be overwritten by children.
bool store_buffer(const Vector<uint8_t> &p_buffer);
void store_var(const Variant &p_var, bool p_full_objects = false);
bool store_var(const Variant &p_var, bool p_full_objects = false);
virtual void close() = 0;

View File

@ -40,18 +40,6 @@ void FileAccessCompressed::configure(const String &p_magic, Compression::Mode p_
block_size = p_block_size;
}
#define WRITE_FIT(m_bytes) \
{ \
if (write_pos + (m_bytes) > write_max) { \
write_max = write_pos + (m_bytes); \
} \
if (write_max > write_buffer_size) { \
write_buffer_size = next_power_of_2(write_max); \
buffer.resize(write_buffer_size); \
write_ptr = buffer.ptrw(); \
} \
}
Error FileAccessCompressed::open_after_magic(Ref<FileAccess> p_base) {
f = p_base;
cmode = (Compression::Mode)f->get_32();
@ -309,13 +297,23 @@ void FileAccessCompressed::flush() {
// compressed files keep data in memory till close()
}
void FileAccessCompressed::store_buffer(const uint8_t *p_src, uint64_t p_length) {
ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before use.");
ERR_FAIL_COND_MSG(!writing, "File has not been opened in write mode.");
bool FileAccessCompressed::store_buffer(const uint8_t *p_src, uint64_t p_length) {
ERR_FAIL_COND_V_MSG(f.is_null(), false, "File must be opened before use.");
ERR_FAIL_COND_V_MSG(!writing, false, "File has not been opened in write mode.");
if (write_pos + (p_length) > write_max) {
write_max = write_pos + (p_length);
}
if (write_max > write_buffer_size) {
write_buffer_size = next_power_of_2(write_max);
ERR_FAIL_COND_V(buffer.resize(write_buffer_size) != OK, false);
write_ptr = buffer.ptrw();
}
WRITE_FIT(p_length);
memcpy(write_ptr + write_pos, p_src, p_length);
write_pos += p_length;
return true;
}
bool FileAccessCompressed::file_exists(const String &p_name) {

View File

@ -89,7 +89,7 @@ public:
virtual Error resize(int64_t p_length) override { return ERR_UNAVAILABLE; }
virtual void flush() override;
virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) override;
virtual bool store_buffer(const uint8_t *p_src, uint64_t p_length) override;
virtual bool file_exists(const String &p_name) override; ///< return true if a file exists

View File

@ -228,16 +228,17 @@ Error FileAccessEncrypted::get_error() const {
return eofed ? ERR_FILE_EOF : OK;
}
void FileAccessEncrypted::store_buffer(const uint8_t *p_src, uint64_t p_length) {
ERR_FAIL_COND_MSG(!writing, "File has not been opened in write mode.");
ERR_FAIL_COND(!p_src && p_length > 0);
bool FileAccessEncrypted::store_buffer(const uint8_t *p_src, uint64_t p_length) {
ERR_FAIL_COND_V_MSG(!writing, false, "File has not been opened in write mode.");
ERR_FAIL_COND_V(!p_src && p_length > 0, false);
if (pos + p_length >= get_length()) {
data.resize(pos + p_length);
ERR_FAIL_COND_V(data.resize(pos + p_length) != OK, false);
}
memcpy(data.ptrw() + pos, p_src, p_length);
pos += p_length;
return true;
}
void FileAccessEncrypted::flush() {

View File

@ -82,7 +82,7 @@ public:
virtual Error resize(int64_t p_length) override { return ERR_UNAVAILABLE; }
virtual void flush() override;
virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) override; ///< store an array of bytes
virtual bool store_buffer(const uint8_t *p_src, uint64_t p_length) override; ///< store an array of bytes
virtual bool file_exists(const String &p_name) override; ///< return true if a file exists

View File

@ -147,16 +147,16 @@ void FileAccessMemory::flush() {
ERR_FAIL_NULL(data);
}
void FileAccessMemory::store_buffer(const uint8_t *p_src, uint64_t p_length) {
ERR_FAIL_COND(!p_src && p_length > 0);
bool FileAccessMemory::store_buffer(const uint8_t *p_src, uint64_t p_length) {
ERR_FAIL_COND_V(!p_src && p_length > 0, false);
uint64_t left = length - pos;
uint64_t write = MIN(p_length, left);
if (write < p_length) {
WARN_PRINT("Writing less data than requested");
}
memcpy(&data[pos], p_src, write);
pos += write;
ERR_FAIL_COND_V_MSG(write < p_length, false, "Writing less data than requested.");
return true;
}

View File

@ -61,7 +61,7 @@ public:
virtual Error resize(int64_t p_length) override { return ERR_UNAVAILABLE; }
virtual void flush() override;
virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) override; ///< store an array of bytes
virtual bool store_buffer(const uint8_t *p_src, uint64_t p_length) override; ///< store an array of bytes
virtual bool file_exists(const String &p_name) override; ///< return true if a file exists

View File

@ -417,8 +417,8 @@ void FileAccessPack::flush() {
ERR_FAIL();
}
void FileAccessPack::store_buffer(const uint8_t *p_src, uint64_t p_length) {
ERR_FAIL();
bool FileAccessPack::store_buffer(const uint8_t *p_src, uint64_t p_length) {
ERR_FAIL_V(false);
}
bool FileAccessPack::file_exists(const String &p_name) {

View File

@ -184,7 +184,7 @@ public:
virtual Error resize(int64_t p_length) override { return ERR_UNAVAILABLE; }
virtual void flush() override;
virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) override;
virtual bool store_buffer(const uint8_t *p_src, uint64_t p_length) override;
virtual bool file_exists(const String &p_name) override;

View File

@ -322,8 +322,8 @@ void FileAccessZip::flush() {
ERR_FAIL();
}
void FileAccessZip::store_buffer(const uint8_t *p_src, uint64_t p_length) {
ERR_FAIL();
bool FileAccessZip::store_buffer(const uint8_t *p_src, uint64_t p_length) {
ERR_FAIL_V(false);
}
bool FileAccessZip::file_exists(const String &p_name) {

View File

@ -101,7 +101,7 @@ public:
virtual Error resize(int64_t p_length) override { return ERR_UNAVAILABLE; }
virtual void flush() override;
virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) override;
virtual bool store_buffer(const uint8_t *p_src, uint64_t p_length) override;
virtual bool file_exists(const String &p_name) override; ///< return true if a file exists

View File

@ -381,20 +381,22 @@
</description>
</method>
<method name="store_8">
<return type="void" />
<return type="bool" />
<param index="0" name="value" type="int" />
<description>
Stores an integer as 8 bits in the file.
[b]Note:[/b] The [param value] should lie in the interval [code][0, 255][/code]. Any other value will overflow and wrap around.
[b]Note:[/b] If an error occurs, the resulting value of the file position indicator is indeterminate.
To store a signed integer, use [method store_64], or convert it manually (see [method store_16] for an example).
</description>
</method>
<method name="store_16">
<return type="void" />
<return type="bool" />
<param index="0" name="value" type="int" />
<description>
Stores an integer as 16 bits in the file.
[b]Note:[/b] The [param value] should lie in the interval [code][0, 2^16 - 1][/code]. Any other value will overflow and wrap around.
[b]Note:[/b] If an error occurs, the resulting value of the file position indicator is indeterminate.
To store a signed integer, use [method store_64] or store a signed integer from the interval [code][-2^15, 2^15 - 1][/code] (i.e. keeping one bit for the signedness) and compute its sign manually when reading. For example:
[codeblocks]
[gdscript]
@ -431,97 +433,108 @@
</description>
</method>
<method name="store_32">
<return type="void" />
<return type="bool" />
<param index="0" name="value" type="int" />
<description>
Stores an integer as 32 bits in the file.
[b]Note:[/b] The [param value] should lie in the interval [code][0, 2^32 - 1][/code]. Any other value will overflow and wrap around.
[b]Note:[/b] If an error occurs, the resulting value of the file position indicator is indeterminate.
To store a signed integer, use [method store_64], or convert it manually (see [method store_16] for an example).
</description>
</method>
<method name="store_64">
<return type="void" />
<return type="bool" />
<param index="0" name="value" type="int" />
<description>
Stores an integer as 64 bits in the file.
[b]Note:[/b] The [param value] must lie in the interval [code][-2^63, 2^63 - 1][/code] (i.e. be a valid [int] value).
[b]Note:[/b] If an error occurs, the resulting value of the file position indicator is indeterminate.
</description>
</method>
<method name="store_buffer">
<return type="void" />
<return type="bool" />
<param index="0" name="buffer" type="PackedByteArray" />
<description>
Stores the given array of bytes in the file.
[b]Note:[/b] If an error occurs, the resulting value of the file position indicator is indeterminate.
</description>
</method>
<method name="store_csv_line">
<return type="void" />
<return type="bool" />
<param index="0" name="values" type="PackedStringArray" />
<param index="1" name="delim" type="String" default="&quot;,&quot;" />
<description>
Store the given [PackedStringArray] in the file as a line formatted in the CSV (Comma-Separated Values) format. You can pass a different delimiter [param delim] to use other than the default [code]","[/code] (comma). This delimiter must be one-character long.
Text will be encoded as UTF-8.
[b]Note:[/b] If an error occurs, the resulting value of the file position indicator is indeterminate.
</description>
</method>
<method name="store_double">
<return type="void" />
<return type="bool" />
<param index="0" name="value" type="float" />
<description>
Stores a floating-point number as 64 bits in the file.
[b]Note:[/b] If an error occurs, the resulting value of the file position indicator is indeterminate.
</description>
</method>
<method name="store_float">
<return type="void" />
<return type="bool" />
<param index="0" name="value" type="float" />
<description>
Stores a floating-point number as 32 bits in the file.
[b]Note:[/b] If an error occurs, the resulting value of the file position indicator is indeterminate.
</description>
</method>
<method name="store_half">
<return type="void" />
<return type="bool" />
<param index="0" name="value" type="float" />
<description>
Stores a half-precision floating-point number as 16 bits in the file.
</description>
</method>
<method name="store_line">
<return type="void" />
<return type="bool" />
<param index="0" name="line" type="String" />
<description>
Stores [param line] in the file followed by a newline character ([code]\n[/code]), encoding the text as UTF-8.
[b]Note:[/b] If an error occurs, the resulting value of the file position indicator is indeterminate.
</description>
</method>
<method name="store_pascal_string">
<return type="void" />
<return type="bool" />
<param index="0" name="string" type="String" />
<description>
Stores the given [String] as a line in the file in Pascal format (i.e. also store the length of the string).
Text will be encoded as UTF-8.
[b]Note:[/b] If an error occurs, the resulting value of the file position indicator is indeterminate.
</description>
</method>
<method name="store_real">
<return type="void" />
<return type="bool" />
<param index="0" name="value" type="float" />
<description>
Stores a floating-point number in the file.
[b]Note:[/b] If an error occurs, the resulting value of the file position indicator is indeterminate.
</description>
</method>
<method name="store_string">
<return type="void" />
<return type="bool" />
<param index="0" name="string" type="String" />
<description>
Stores [param string] in the file without a newline character ([code]\n[/code]), encoding the text as UTF-8.
[b]Note:[/b] This method is intended to be used to write text files. The string is stored as a UTF-8 encoded buffer without string length or terminating zero, which means that it can't be loaded back easily. If you want to store a retrievable string in a binary file, consider using [method store_pascal_string] instead. For retrieving strings from a text file, you can use [code]get_buffer(length).get_string_from_utf8()[/code] (if you know the length) or [method get_as_text].
[b]Note:[/b] If an error occurs, the resulting value of the file position indicator is indeterminate.
</description>
</method>
<method name="store_var">
<return type="void" />
<return type="bool" />
<param index="0" name="value" type="Variant" />
<param index="1" name="full_objects" type="bool" default="false" />
<description>
Stores any Variant value in the file. If [param full_objects] is [code]true[/code], encoding objects is allowed (and can potentially include code).
Internally, this uses the same encoding mechanism as the [method @GlobalScope.var_to_bytes] method.
[b]Note:[/b] Not all properties are included. Only properties that are configured with the [constant PROPERTY_USAGE_STORAGE] flag set will be serialized. You can add a new usage flag to a property by overriding the [method Object._get_property_list] method in your class. You can also check how property usage is configured by calling [method Object._get_property_list]. See [enum PropertyUsageFlags] for the possible usage flags.
[b]Note:[/b] If an error occurs, the resulting value of the file position indicator is indeterminate.
</description>
</method>
</methods>

View File

@ -295,10 +295,10 @@ void FileAccessUnix::flush() {
fflush(f);
}
void FileAccessUnix::store_buffer(const uint8_t *p_src, uint64_t p_length) {
ERR_FAIL_NULL_MSG(f, "File must be opened before use.");
ERR_FAIL_COND(!p_src && p_length > 0);
ERR_FAIL_COND(fwrite(p_src, 1, p_length, f) != p_length);
bool FileAccessUnix::store_buffer(const uint8_t *p_src, uint64_t p_length) {
ERR_FAIL_NULL_V_MSG(f, false, "File must be opened before use.");
ERR_FAIL_COND_V(!p_src && p_length > 0, false);
return fwrite(p_src, 1, p_length, f) == p_length;
}
bool FileAccessUnix::file_exists(const String &p_path) {

View File

@ -77,7 +77,7 @@ public:
virtual Error resize(int64_t p_length) override;
virtual void flush() override;
virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) override; ///< store an array of bytes
virtual bool store_buffer(const uint8_t *p_src, uint64_t p_length) override; ///< store an array of bytes
virtual bool file_exists(const String &p_path) override; ///< return true if a file exists

View File

@ -150,14 +150,16 @@ Error FileAccessUnixPipe::get_error() const {
return last_error;
}
void FileAccessUnixPipe::store_buffer(const uint8_t *p_src, uint64_t p_length) {
ERR_FAIL_COND_MSG(fd[1] < 0, "Pipe must be opened before use.");
ERR_FAIL_COND(!p_src && p_length > 0);
bool FileAccessUnixPipe::store_buffer(const uint8_t *p_src, uint64_t p_length) {
ERR_FAIL_COND_V_MSG(fd[1] < 0, false, "Pipe must be opened before use.");
ERR_FAIL_COND_V(!p_src && p_length > 0, false);
if (::write(fd[1], p_src, p_length) != (ssize_t)p_length) {
last_error = ERR_FILE_CANT_WRITE;
return false;
} else {
last_error = OK;
return true;
}
}

View File

@ -71,7 +71,7 @@ public:
virtual Error resize(int64_t p_length) override { return ERR_UNAVAILABLE; }
virtual void flush() override {}
virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) override; ///< store an array of bytes
virtual bool store_buffer(const uint8_t *p_src, uint64_t p_length) override; ///< store an array of bytes
virtual bool file_exists(const String &p_path) override { return false; }

View File

@ -372,9 +372,9 @@ void FileAccessWindows::flush() {
}
}
void FileAccessWindows::store_buffer(const uint8_t *p_src, uint64_t p_length) {
ERR_FAIL_NULL(f);
ERR_FAIL_COND(!p_src && p_length > 0);
bool FileAccessWindows::store_buffer(const uint8_t *p_src, uint64_t p_length) {
ERR_FAIL_NULL_V(f, false);
ERR_FAIL_COND_V(!p_src && p_length > 0, false);
if (flags == READ_WRITE || flags == WRITE_READ) {
if (prev_op == READ) {
@ -385,7 +385,7 @@ void FileAccessWindows::store_buffer(const uint8_t *p_src, uint64_t p_length) {
prev_op = WRITE;
}
ERR_FAIL_COND(fwrite(p_src, 1, p_length, f) != (size_t)p_length);
return fwrite(p_src, 1, p_length, f) == (size_t)p_length;
}
bool FileAccessWindows::file_exists(const String &p_name) {

View File

@ -75,7 +75,7 @@ public:
virtual Error resize(int64_t p_length) override;
virtual void flush() override;
virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) override; ///< store an array of bytes
virtual bool store_buffer(const uint8_t *p_src, uint64_t p_length) override; ///< store an array of bytes
virtual bool file_exists(const String &p_name) override; ///< return true if a file exists

View File

@ -119,16 +119,18 @@ Error FileAccessWindowsPipe::get_error() const {
return last_error;
}
void FileAccessWindowsPipe::store_buffer(const uint8_t *p_src, uint64_t p_length) {
ERR_FAIL_COND_MSG(fd[1] == nullptr, "Pipe must be opened before use.");
ERR_FAIL_COND(!p_src && p_length > 0);
bool FileAccessWindowsPipe::store_buffer(const uint8_t *p_src, uint64_t p_length) {
ERR_FAIL_COND_V_MSG(fd[1] == nullptr, false, "Pipe must be opened before use.");
ERR_FAIL_COND_V(!p_src && p_length > 0, false);
DWORD read = -1;
bool ok = WriteFile(fd[1], p_src, p_length, &read, nullptr);
if (!ok || read != p_length) {
last_error = ERR_FILE_CANT_WRITE;
return false;
} else {
last_error = OK;
return true;
}
}

View File

@ -70,7 +70,7 @@ public:
virtual Error resize(int64_t p_length) override { return ERR_UNAVAILABLE; }
virtual void flush() override {}
virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) override; ///< store an array of bytes
virtual bool store_buffer(const uint8_t *p_src, uint64_t p_length) override; ///< store an array of bytes
virtual bool file_exists(const String &p_name) override { return false; }

View File

@ -178,3 +178,23 @@ Validate extension JSON: Error: Field 'classes/RenderingDevice/methods/draw_list
Draw lists no longer require the initial and final action for color and depth attachments to be specified.
Draw lists can now specify if a particular color, depth, or stencil attachment should be cleared.
GH-78289
--------
Validate extension JSON: JSON file: Field was added in a way that breaks compatibility 'classes/FileAccess/methods/store_16': return_value
Validate extension JSON: JSON file: Field was added in a way that breaks compatibility 'classes/FileAccess/methods/store_32': return_value
Validate extension JSON: JSON file: Field was added in a way that breaks compatibility 'classes/FileAccess/methods/store_64': return_value
Validate extension JSON: JSON file: Field was added in a way that breaks compatibility 'classes/FileAccess/methods/store_8': return_value
Validate extension JSON: JSON file: Field was added in a way that breaks compatibility 'classes/FileAccess/methods/store_buffer': return_value
Validate extension JSON: JSON file: Field was added in a way that breaks compatibility 'classes/FileAccess/methods/store_csv_line': return_value
Validate extension JSON: JSON file: Field was added in a way that breaks compatibility 'classes/FileAccess/methods/store_double': return_value
Validate extension JSON: JSON file: Field was added in a way that breaks compatibility 'classes/FileAccess/methods/store_half': return_value
Validate extension JSON: JSON file: Field was added in a way that breaks compatibility 'classes/FileAccess/methods/store_float': return_value
Validate extension JSON: JSON file: Field was added in a way that breaks compatibility 'classes/FileAccess/methods/store_line': return_value
Validate extension JSON: JSON file: Field was added in a way that breaks compatibility 'classes/FileAccess/methods/store_pascal_string': return_value
Validate extension JSON: JSON file: Field was added in a way that breaks compatibility 'classes/FileAccess/methods/store_real': return_value
Validate extension JSON: JSON file: Field was added in a way that breaks compatibility 'classes/FileAccess/methods/store_string': return_value
Validate extension JSON: JSON file: Field was added in a way that breaks compatibility 'classes/FileAccess/methods/store_var': return_value
Added return values. Compatibility method registered.

View File

@ -140,8 +140,8 @@ void FileAccessAndroid::flush() {
ERR_FAIL();
}
void FileAccessAndroid::store_buffer(const uint8_t *p_src, uint64_t p_length) {
ERR_FAIL();
bool FileAccessAndroid::store_buffer(const uint8_t *p_src, uint64_t p_length) {
ERR_FAIL_V(false);
}
bool FileAccessAndroid::file_exists(const String &p_path) {

View File

@ -73,7 +73,7 @@ public:
virtual Error get_error() const override; // get last error
virtual void flush() override;
virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) override;
virtual bool store_buffer(const uint8_t *p_src, uint64_t p_length) override;
virtual bool file_exists(const String &p_path) override; // return true if a file exists

View File

@ -234,19 +234,23 @@ uint64_t FileAccessFilesystemJAndroid::get_buffer(uint8_t *p_dst, uint64_t p_len
}
}
void FileAccessFilesystemJAndroid::store_buffer(const uint8_t *p_src, uint64_t p_length) {
bool FileAccessFilesystemJAndroid::store_buffer(const uint8_t *p_src, uint64_t p_length) {
if (_file_write) {
ERR_FAIL_COND_MSG(!is_open(), "File must be opened before use.");
ERR_FAIL_COND_V_MSG(!is_open(), false, "File must be opened before use.");
ERR_FAIL_COND_V(!p_src && p_length > 0, false);
if (p_length == 0) {
return;
return true;
}
JNIEnv *env = get_jni_env();
ERR_FAIL_NULL(env);
ERR_FAIL_NULL_V(env, false);
jobject j_buffer = env->NewDirectByteBuffer((void *)p_src, p_length);
env->CallVoidMethod(file_access_handler, _file_write, id, j_buffer);
bool ok = env->CallBooleanMethod(file_access_handler, _file_write, id, j_buffer);
env->DeleteLocalRef(j_buffer);
return ok;
} else {
return false;
}
}
@ -324,7 +328,7 @@ void FileAccessFilesystemJAndroid::setup(jobject p_file_access_handler) {
_file_seek_end = env->GetMethodID(cls, "fileSeekFromEnd", "(IJ)V");
_file_read = env->GetMethodID(cls, "fileRead", "(ILjava/nio/ByteBuffer;)I");
_file_close = env->GetMethodID(cls, "fileClose", "(I)V");
_file_write = env->GetMethodID(cls, "fileWrite", "(ILjava/nio/ByteBuffer;)V");
_file_write = env->GetMethodID(cls, "fileWrite", "(ILjava/nio/ByteBuffer;)Z");
_file_flush = env->GetMethodID(cls, "fileFlush", "(I)V");
_file_exists = env->GetMethodID(cls, "fileExists", "(Ljava/lang/String;)Z");
_file_last_modified = env->GetMethodID(cls, "fileLastModified", "(Ljava/lang/String;)J");

View File

@ -84,7 +84,7 @@ public:
virtual Error get_error() const override; ///< get last error
virtual void flush() override;
virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) override;
virtual bool store_buffer(const uint8_t *p_src, uint64_t p_length) override;
virtual bool file_exists(const String &p_path) override; ///< return true if a file exists

View File

@ -145,7 +145,8 @@ internal class AssetData(context: Context, private val filePath: String, accessF
}
}
override fun write(buffer: ByteBuffer) {
override fun write(buffer: ByteBuffer): Boolean {
Log.w(TAG, "write() is not supported.")
return false
}
}

View File

@ -169,7 +169,7 @@ internal abstract class DataAccess {
abstract fun position(): Long
abstract fun size(): Long
abstract fun read(buffer: ByteBuffer): Int
abstract fun write(buffer: ByteBuffer)
abstract fun write(buffer: ByteBuffer): Boolean
fun seekFromEnd(positionFromEnd: Long) {
val positionFromBeginning = max(0, size() - positionFromEnd)
@ -254,14 +254,16 @@ internal abstract class DataAccess {
}
}
override fun write(buffer: ByteBuffer) {
override fun write(buffer: ByteBuffer): Boolean {
try {
val writtenBytes = fileChannel.write(buffer)
if (writtenBytes > 0) {
endOfFile = false
}
return true
} catch (e: IOException) {
Log.w(TAG, "Exception while writing to file $filePath.", e)
return false
}
}
}

View File

@ -191,12 +191,12 @@ class FileAccessHandler(val context: Context) {
return files[fileId].read(byteBuffer)
}
fun fileWrite(fileId: Int, byteBuffer: ByteBuffer?) {
fun fileWrite(fileId: Int, byteBuffer: ByteBuffer?): Boolean {
if (!hasFileId(fileId) || byteBuffer == null) {
return
return false
}
files[fileId].write(byteBuffer)
return files[fileId].write(byteBuffer)
}
fun fileFlush(fileId: Int) {