Browse Source

[FileAccess] Return error codes from `store_*` methods.

bruvzg 2 years ago
parent
commit
a4b17e7852

+ 72 - 1
core/io/file_access.compat.inc

@@ -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>());
 	return open_encrypted(p_path, p_mode_flags, p_key, Vector<uint8_t>());
 }
 }
 
 
+void FileAccess::store_8_bind_compat_78289(uint8_t p_dest) {
+	store_8(p_dest);
+}
+
+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() {
 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_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 // DISABLE_DEPRECATED
+#endif

+ 48 - 37
core/io/file_access.cpp

@@ -495,56 +495,56 @@ String FileAccess::get_as_utf8_string(bool p_skip_cr) const {
 	return s;
 	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) {
 	if (big_endian) {
 		p_dest = BSWAP16(p_dest);
 		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) {
 	if (big_endian) {
 		p_dest = BSWAP32(p_dest);
 		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) {
 	if (big_endian) {
 		p_dest = BSWAP64(p_dest);
 		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) {
 	if constexpr (sizeof(real_t) == 4) {
-		store_float(p_real);
+		return store_float(p_real);
 	} else {
 	} 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;
 	MarshallFloat m;
 	m.f = p_dest;
 	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;
 	MarshallDouble m;
 	m.d = p_dest;
 	m.d = p_dest;
-	store_64(m.l);
+	return store_64(m.l);
 }
 }
 
 
 uint64_t FileAccess::get_modified_time(const String &p_file) {
 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;
 	return err;
 }
 }
 
 
-void FileAccess::store_string(const String &p_string) {
+bool FileAccess::store_string(const String &p_string) {
 	if (p_string.length() == 0) {
 	if (p_string.length() == 0) {
-		return;
+		return true;
 	}
 	}
 
 
 	CharString cs = p_string.utf8();
 	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();
 	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() {
 String FileAccess::get_pascal_string() {
@@ -655,13 +654,12 @@ String FileAccess::get_pascal_string() {
 	return ret;
 	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 = "";
 	String line = "";
 	int size = p_values.size();
 	int size = p_values.size();
@@ -678,30 +676,43 @@ void FileAccess::store_csv_line(const Vector<String> &p_values, const String &p_
 		line += value;
 		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();
 	uint64_t len = p_buffer.size();
+	if (len == 0) {
+		return true;
+	}
+
 	const uint8_t *r = p_buffer.ptr();
 	const uint8_t *r = p_buffer.ptr();
 
 
-	store_buffer(r, len);
+	return store_buffer(r, len);
+}
+
+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;
 }
 }
 
 
-void FileAccess::store_var(const Variant &p_var, bool p_full_objects) {
+bool FileAccess::store_var(const Variant &p_var, bool p_full_objects) {
 	int len;
 	int len;
 	Error err = encode_variant(p_var, nullptr, len, p_full_objects);
 	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;
 	Vector<uint8_t> buff;
 	buff.resize(len);
 	buff.resize(len);
 
 
 	uint8_t *w = buff.ptrw();
 	uint8_t *w = buff.ptrw();
 	err = encode_variant(p_var, &w[0], len, p_full_objects);
 	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) {
 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_float", "value"), &FileAccess::store_float);
 	ClassDB::bind_method(D_METHOD("store_double", "value"), &FileAccess::store_double);
 	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_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_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_csv_line", "values", "delim"), &FileAccess::store_csv_line, DEFVAL(","));
 	ClassDB::bind_method(D_METHOD("store_string", "string"), &FileAccess::store_string);
 	ClassDB::bind_method(D_METHOD("store_string", "string"), &FileAccess::store_string);

+ 31 - 15
core/io/file_access.h

@@ -112,6 +112,21 @@ protected:
 #ifndef DISABLE_DEPRECATED
 #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);
 	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();
 	static void _bind_compatibility_methods();
 #endif
 #endif
 
 
@@ -164,6 +179,7 @@ public:
 	virtual String get_as_utf8_string(bool p_skip_cr = false) const;
 	virtual String get_as_utf8_string(bool p_skip_cr = false) const;
 
 
 	/**
 	/**
+
 	 * Use this for files WRITTEN in _big_ endian machines (ie, amiga/mac)
 	 * Use this for files WRITTEN in _big_ endian machines (ie, amiga/mac)
 	 * It's not about the current CPU type but file formats.
 	 * It's not about the current CPU type but file formats.
 	 * This flag gets reset to `false` (little endian) on each open.
 	 * 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 Error resize(int64_t p_length) = 0;
 	virtual void flush() = 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 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;
 	virtual void close() = 0;
 
 

+ 14 - 16
core/io/file_access_compressed.cpp

@@ -40,18 +40,6 @@ void FileAccessCompressed::configure(const String &p_magic, Compression::Mode p_
 	block_size = p_block_size;
 	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) {
 Error FileAccessCompressed::open_after_magic(Ref<FileAccess> p_base) {
 	f = p_base;
 	f = p_base;
 	cmode = (Compression::Mode)f->get_32();
 	cmode = (Compression::Mode)f->get_32();
@@ -309,13 +297,23 @@ void FileAccessCompressed::flush() {
 	// compressed files keep data in memory till close()
 	// 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);
 	memcpy(write_ptr + write_pos, p_src, p_length);
+
 	write_pos += p_length;
 	write_pos += p_length;
+	return true;
 }
 }
 
 
 bool FileAccessCompressed::file_exists(const String &p_name) {
 bool FileAccessCompressed::file_exists(const String &p_name) {

+ 1 - 1
core/io/file_access_compressed.h

@@ -89,7 +89,7 @@ public:
 
 
 	virtual Error resize(int64_t p_length) override { return ERR_UNAVAILABLE; }
 	virtual Error resize(int64_t p_length) override { return ERR_UNAVAILABLE; }
 	virtual void flush() override;
 	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
 	virtual bool file_exists(const String &p_name) override; ///< return true if a file exists
 
 

+ 5 - 4
core/io/file_access_encrypted.cpp

@@ -228,16 +228,17 @@ Error FileAccessEncrypted::get_error() const {
 	return eofed ? ERR_FILE_EOF : OK;
 	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()) {
 	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);
 	memcpy(data.ptrw() + pos, p_src, p_length);
 	pos += p_length;
 	pos += p_length;
+	return true;
 }
 }
 
 
 void FileAccessEncrypted::flush() {
 void FileAccessEncrypted::flush() {

+ 1 - 1
core/io/file_access_encrypted.h

@@ -82,7 +82,7 @@ public:
 
 
 	virtual Error resize(int64_t p_length) override { return ERR_UNAVAILABLE; }
 	virtual Error resize(int64_t p_length) override { return ERR_UNAVAILABLE; }
 	virtual void flush() 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
 	virtual bool file_exists(const String &p_name) override; ///< return true if a file exists
 
 

+ 6 - 6
core/io/file_access_memory.cpp

@@ -147,16 +147,16 @@ void FileAccessMemory::flush() {
 	ERR_FAIL_NULL(data);
 	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 left = length - pos;
 	uint64_t write = MIN(p_length, left);
 	uint64_t write = MIN(p_length, left);
 
 
-	if (write < p_length) {
-		WARN_PRINT("Writing less data than requested");
-	}
-
 	memcpy(&data[pos], p_src, write);
 	memcpy(&data[pos], p_src, write);
 	pos += write;
 	pos += write;
+
+	ERR_FAIL_COND_V_MSG(write < p_length, false, "Writing less data than requested.");
+
+	return true;
 }
 }

+ 1 - 1
core/io/file_access_memory.h

@@ -61,7 +61,7 @@ public:
 
 
 	virtual Error resize(int64_t p_length) override { return ERR_UNAVAILABLE; }
 	virtual Error resize(int64_t p_length) override { return ERR_UNAVAILABLE; }
 	virtual void flush() 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
 	virtual bool file_exists(const String &p_name) override; ///< return true if a file exists
 
 

+ 2 - 2
core/io/file_access_pack.cpp

@@ -417,8 +417,8 @@ void FileAccessPack::flush() {
 	ERR_FAIL();
 	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) {
 bool FileAccessPack::file_exists(const String &p_name) {

+ 1 - 1
core/io/file_access_pack.h

@@ -184,7 +184,7 @@ public:
 
 
 	virtual Error resize(int64_t p_length) override { return ERR_UNAVAILABLE; }
 	virtual Error resize(int64_t p_length) override { return ERR_UNAVAILABLE; }
 	virtual void flush() override;
 	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;
 	virtual bool file_exists(const String &p_name) override;
 
 

+ 2 - 2
core/io/file_access_zip.cpp

@@ -322,8 +322,8 @@ void FileAccessZip::flush() {
 	ERR_FAIL();
 	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) {
 bool FileAccessZip::file_exists(const String &p_name) {

+ 1 - 1
core/io/file_access_zip.h

@@ -101,7 +101,7 @@ public:
 
 
 	virtual Error resize(int64_t p_length) override { return ERR_UNAVAILABLE; }
 	virtual Error resize(int64_t p_length) override { return ERR_UNAVAILABLE; }
 	virtual void flush() override;
 	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
 	virtual bool file_exists(const String &p_name) override; ///< return true if a file exists
 
 

+ 27 - 14
doc/classes/FileAccess.xml

@@ -381,20 +381,22 @@
 			</description>
 			</description>
 		</method>
 		</method>
 		<method name="store_8">
 		<method name="store_8">
-			<return type="void" />
+			<return type="bool" />
 			<param index="0" name="value" type="int" />
 			<param index="0" name="value" type="int" />
 			<description>
 			<description>
 				Stores an integer as 8 bits in the file.
 				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] 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).
 				To store a signed integer, use [method store_64], or convert it manually (see [method store_16] for an example).
 			</description>
 			</description>
 		</method>
 		</method>
 		<method name="store_16">
 		<method name="store_16">
-			<return type="void" />
+			<return type="bool" />
 			<param index="0" name="value" type="int" />
 			<param index="0" name="value" type="int" />
 			<description>
 			<description>
 				Stores an integer as 16 bits in the file.
 				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] 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:
 				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]
 				[codeblocks]
 				[gdscript]
 				[gdscript]
@@ -431,97 +433,108 @@
 			</description>
 			</description>
 		</method>
 		</method>
 		<method name="store_32">
 		<method name="store_32">
-			<return type="void" />
+			<return type="bool" />
 			<param index="0" name="value" type="int" />
 			<param index="0" name="value" type="int" />
 			<description>
 			<description>
 				Stores an integer as 32 bits in the file.
 				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] 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).
 				To store a signed integer, use [method store_64], or convert it manually (see [method store_16] for an example).
 			</description>
 			</description>
 		</method>
 		</method>
 		<method name="store_64">
 		<method name="store_64">
-			<return type="void" />
+			<return type="bool" />
 			<param index="0" name="value" type="int" />
 			<param index="0" name="value" type="int" />
 			<description>
 			<description>
 				Stores an integer as 64 bits in the file.
 				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] 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>
 			</description>
 		</method>
 		</method>
 		<method name="store_buffer">
 		<method name="store_buffer">
-			<return type="void" />
+			<return type="bool" />
 			<param index="0" name="buffer" type="PackedByteArray" />
 			<param index="0" name="buffer" type="PackedByteArray" />
 			<description>
 			<description>
 				Stores the given array of bytes in the file.
 				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>
 			</description>
 		</method>
 		</method>
 		<method name="store_csv_line">
 		<method name="store_csv_line">
-			<return type="void" />
+			<return type="bool" />
 			<param index="0" name="values" type="PackedStringArray" />
 			<param index="0" name="values" type="PackedStringArray" />
 			<param index="1" name="delim" type="String" default="&quot;,&quot;" />
 			<param index="1" name="delim" type="String" default="&quot;,&quot;" />
 			<description>
 			<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.
 				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.
 				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>
 			</description>
 		</method>
 		</method>
 		<method name="store_double">
 		<method name="store_double">
-			<return type="void" />
+			<return type="bool" />
 			<param index="0" name="value" type="float" />
 			<param index="0" name="value" type="float" />
 			<description>
 			<description>
 				Stores a floating-point number as 64 bits in the file.
 				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>
 			</description>
 		</method>
 		</method>
 		<method name="store_float">
 		<method name="store_float">
-			<return type="void" />
+			<return type="bool" />
 			<param index="0" name="value" type="float" />
 			<param index="0" name="value" type="float" />
 			<description>
 			<description>
 				Stores a floating-point number as 32 bits in the file.
 				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>
 			</description>
 		</method>
 		</method>
 		<method name="store_half">
 		<method name="store_half">
-			<return type="void" />
+			<return type="bool" />
 			<param index="0" name="value" type="float" />
 			<param index="0" name="value" type="float" />
 			<description>
 			<description>
 				Stores a half-precision floating-point number as 16 bits in the file.
 				Stores a half-precision floating-point number as 16 bits in the file.
 			</description>
 			</description>
 		</method>
 		</method>
 		<method name="store_line">
 		<method name="store_line">
-			<return type="void" />
+			<return type="bool" />
 			<param index="0" name="line" type="String" />
 			<param index="0" name="line" type="String" />
 			<description>
 			<description>
 				Stores [param line] in the file followed by a newline character ([code]\n[/code]), encoding the text as UTF-8.
 				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>
 			</description>
 		</method>
 		</method>
 		<method name="store_pascal_string">
 		<method name="store_pascal_string">
-			<return type="void" />
+			<return type="bool" />
 			<param index="0" name="string" type="String" />
 			<param index="0" name="string" type="String" />
 			<description>
 			<description>
 				Stores the given [String] as a line in the file in Pascal format (i.e. also store the length of the string).
 				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.
 				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>
 			</description>
 		</method>
 		</method>
 		<method name="store_real">
 		<method name="store_real">
-			<return type="void" />
+			<return type="bool" />
 			<param index="0" name="value" type="float" />
 			<param index="0" name="value" type="float" />
 			<description>
 			<description>
 				Stores a floating-point number in the file.
 				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>
 			</description>
 		</method>
 		</method>
 		<method name="store_string">
 		<method name="store_string">
-			<return type="void" />
+			<return type="bool" />
 			<param index="0" name="string" type="String" />
 			<param index="0" name="string" type="String" />
 			<description>
 			<description>
 				Stores [param string] in the file without a newline character ([code]\n[/code]), encoding the text as UTF-8.
 				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] 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>
 			</description>
 		</method>
 		</method>
 		<method name="store_var">
 		<method name="store_var">
-			<return type="void" />
+			<return type="bool" />
 			<param index="0" name="value" type="Variant" />
 			<param index="0" name="value" type="Variant" />
 			<param index="1" name="full_objects" type="bool" default="false" />
 			<param index="1" name="full_objects" type="bool" default="false" />
 			<description>
 			<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).
 				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.
 				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] 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>
 			</description>
 		</method>
 		</method>
 	</methods>
 	</methods>

+ 4 - 4
drivers/unix/file_access_unix.cpp

@@ -295,10 +295,10 @@ void FileAccessUnix::flush() {
 	fflush(f);
 	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) {
 bool FileAccessUnix::file_exists(const String &p_path) {

+ 1 - 1
drivers/unix/file_access_unix.h

@@ -77,7 +77,7 @@ public:
 
 
 	virtual Error resize(int64_t p_length) override;
 	virtual Error resize(int64_t p_length) override;
 	virtual void flush() 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
 	virtual bool file_exists(const String &p_path) override; ///< return true if a file exists
 
 

+ 5 - 3
drivers/unix/file_access_unix_pipe.cpp

@@ -150,14 +150,16 @@ Error FileAccessUnixPipe::get_error() const {
 	return last_error;
 	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) {
 	if (::write(fd[1], p_src, p_length) != (ssize_t)p_length) {
 		last_error = ERR_FILE_CANT_WRITE;
 		last_error = ERR_FILE_CANT_WRITE;
+		return false;
 	} else {
 	} else {
 		last_error = OK;
 		last_error = OK;
+		return true;
 	}
 	}
 }
 }
 
 

+ 1 - 1
drivers/unix/file_access_unix_pipe.h

@@ -71,7 +71,7 @@ public:
 
 
 	virtual Error resize(int64_t p_length) override { return ERR_UNAVAILABLE; }
 	virtual Error resize(int64_t p_length) override { return ERR_UNAVAILABLE; }
 	virtual void flush() 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 false; }
 	virtual bool file_exists(const String &p_path) override { return false; }
 
 

+ 4 - 4
drivers/windows/file_access_windows.cpp

@@ -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 (flags == READ_WRITE || flags == WRITE_READ) {
 		if (prev_op == 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;
 		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) {
 bool FileAccessWindows::file_exists(const String &p_name) {

+ 1 - 1
drivers/windows/file_access_windows.h

@@ -75,7 +75,7 @@ public:
 
 
 	virtual Error resize(int64_t p_length) override;
 	virtual Error resize(int64_t p_length) override;
 	virtual void flush() 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
 	virtual bool file_exists(const String &p_name) override; ///< return true if a file exists
 
 

+ 5 - 3
drivers/windows/file_access_windows_pipe.cpp

@@ -119,16 +119,18 @@ Error FileAccessWindowsPipe::get_error() const {
 	return last_error;
 	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;
 	DWORD read = -1;
 	bool ok = WriteFile(fd[1], p_src, p_length, &read, nullptr);
 	bool ok = WriteFile(fd[1], p_src, p_length, &read, nullptr);
 	if (!ok || read != p_length) {
 	if (!ok || read != p_length) {
 		last_error = ERR_FILE_CANT_WRITE;
 		last_error = ERR_FILE_CANT_WRITE;
+		return false;
 	} else {
 	} else {
 		last_error = OK;
 		last_error = OK;
+		return true;
 	}
 	}
 }
 }
 
 

+ 1 - 1
drivers/windows/file_access_windows_pipe.h

@@ -70,7 +70,7 @@ public:
 
 
 	virtual Error resize(int64_t p_length) override { return ERR_UNAVAILABLE; }
 	virtual Error resize(int64_t p_length) override { return ERR_UNAVAILABLE; }
 	virtual void flush() 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 false; }
 	virtual bool file_exists(const String &p_name) override { return false; }
 
 

+ 20 - 0
misc/extension_api_validation/4.3-stable.expected

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

+ 2 - 2
platform/android/file_access_android.cpp

@@ -140,8 +140,8 @@ void FileAccessAndroid::flush() {
 	ERR_FAIL();
 	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) {
 bool FileAccessAndroid::file_exists(const String &p_path) {

+ 1 - 1
platform/android/file_access_android.h

@@ -73,7 +73,7 @@ public:
 	virtual Error get_error() const override; // get last error
 	virtual Error get_error() const override; // get last error
 
 
 	virtual void flush() override;
 	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
 	virtual bool file_exists(const String &p_path) override; // return true if a file exists
 
 

+ 10 - 6
platform/android/file_access_filesystem_jandroid.cpp

@@ -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) {
 	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) {
 		if (p_length == 0) {
-			return;
+			return true;
 		}
 		}
 
 
 		JNIEnv *env = get_jni_env();
 		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);
 		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);
 		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_seek_end = env->GetMethodID(cls, "fileSeekFromEnd", "(IJ)V");
 	_file_read = env->GetMethodID(cls, "fileRead", "(ILjava/nio/ByteBuffer;)I");
 	_file_read = env->GetMethodID(cls, "fileRead", "(ILjava/nio/ByteBuffer;)I");
 	_file_close = env->GetMethodID(cls, "fileClose", "(I)V");
 	_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_flush = env->GetMethodID(cls, "fileFlush", "(I)V");
 	_file_exists = env->GetMethodID(cls, "fileExists", "(Ljava/lang/String;)Z");
 	_file_exists = env->GetMethodID(cls, "fileExists", "(Ljava/lang/String;)Z");
 	_file_last_modified = env->GetMethodID(cls, "fileLastModified", "(Ljava/lang/String;)J");
 	_file_last_modified = env->GetMethodID(cls, "fileLastModified", "(Ljava/lang/String;)J");

+ 1 - 1
platform/android/file_access_filesystem_jandroid.h

@@ -84,7 +84,7 @@ public:
 	virtual Error get_error() const override; ///< get last error
 	virtual Error get_error() const override; ///< get last error
 
 
 	virtual void flush() override;
 	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
 	virtual bool file_exists(const String &p_path) override; ///< return true if a file exists
 
 

+ 2 - 1
platform/android/java/lib/src/org/godotengine/godot/io/file/AssetData.kt

@@ -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.")
 		Log.w(TAG, "write() is not supported.")
+		return false
 	}
 	}
 }
 }

+ 4 - 2
platform/android/java/lib/src/org/godotengine/godot/io/file/DataAccess.kt

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

+ 3 - 3
platform/android/java/lib/src/org/godotengine/godot/io/file/FileAccessHandler.kt

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