Skip to content

Commit

Permalink
Make all file access 64-bit (uint64_t)
Browse files Browse the repository at this point in the history
This changes the types of a big number of variables.

General rules:
- Using `uint64_t` in general. We also considered `int64_t` but eventually
  settled on keeping it unsigned, which is also closer to what one would expect
  with `size_t`/`off_t`.
- We only keep `int64_t` for `seek_end` (takes a negative offset from the end)
  and for the `Variant` bindings, since `Variant::INT` is `int64_t`. This means
  we only need to guard against passing negative values in `core_bind.cpp`.
- Using `uint32_t` integers for concepts not needing such a huge range, like
  pages, blocks, etc.

In addition:
- Improve usage of integer types in some related places; namely, `DirAccess`,
  core binds.

Note:
- On Windows, `_ftelli64` reports invalid values when using 32-bit MinGW with
  version < 8.0. This was an upstream bug fixed in 8.0. It breaks support for
  big files on 32-bit Windows builds made with that toolchain. We might add a
  workaround.

Fixes godotengine#44363.
Fixes godotengine/godot-proposals#400.

Co-authored-by: Rémi Verschelde <[email protected]>
  • Loading branch information
RandomShaper and akien-mga committed May 17, 2021
1 parent 9cc17a8 commit 469fa47
Show file tree
Hide file tree
Showing 65 changed files with 326 additions and 342 deletions.
20 changes: 10 additions & 10 deletions core/core_bind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1259,6 +1259,7 @@ String _File::get_path_absolute() const {

void _File::seek(int64_t p_position) {
ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
ERR_FAIL_COND_MSG(p_position < 0, "Seek position must be a positive integer.");
f->seek(p_position);
}

Expand All @@ -1267,12 +1268,12 @@ void _File::seek_end(int64_t p_position) {
f->seek_end(p_position);
}

int64_t _File::get_position() const {
uint64_t _File::get_position() const {
ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
return f->get_position();
}

int64_t _File::get_len() const {
uint64_t _File::get_len() const {
ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
return f->get_len();
}
Expand Down Expand Up @@ -1317,7 +1318,7 @@ real_t _File::get_real() const {
return f->get_real();
}

Vector<uint8_t> _File::get_buffer(int p_length) const {
Vector<uint8_t> _File::get_buffer(int64_t p_length) const {
Vector<uint8_t> data;
ERR_FAIL_COND_V_MSG(!f, data, "File must be opened before use.");

Expand All @@ -1330,8 +1331,7 @@ Vector<uint8_t> _File::get_buffer(int p_length) const {
ERR_FAIL_COND_V_MSG(err != OK, data, "Can't resize data to " + itos(p_length) + " elements.");

uint8_t *w = data.ptrw();
int len = f->get_buffer(&w[0], p_length);
ERR_FAIL_COND_V(len < 0, Vector<uint8_t>());
int64_t len = f->get_buffer(&w[0], p_length);

if (len < p_length) {
data.resize(len);
Expand All @@ -1344,7 +1344,7 @@ String _File::get_as_text() const {
ERR_FAIL_COND_V_MSG(!f, String(), "File must be opened before use.");

String text;
size_t original_pos = f->get_position();
uint64_t original_pos = f->get_position();
f->seek(0);

String l = get_line();
Expand Down Expand Up @@ -1473,7 +1473,7 @@ void _File::store_csv_line(const Vector<String> &p_values, const String &p_delim
void _File::store_buffer(const Vector<uint8_t> &p_buffer) {
ERR_FAIL_COND_MSG(!f, "File must be opened before use.");

int len = p_buffer.size();
uint64_t len = p_buffer.size();
if (len == 0) {
return;
}
Expand Down Expand Up @@ -1721,9 +1721,9 @@ bool _Directory::dir_exists(String p_dir) {
return d->dir_exists(p_dir);
}

int _Directory::get_space_left() {
ERR_FAIL_COND_V_MSG(!is_open(), 0, "Directory must be opened before use.");
return d->get_space_left() / 1024 * 1024; //return value in megabytes, given binding is int
uint64_t _Directory::get_space_left() {
ERR_FAIL_COND_V_MSG(!d, 0, "Directory must be opened before use.");
return d->get_space_left() / 1024 * 1024; // Truncate to closest MiB.
}

Error _Directory::copy(String p_from, String p_to) {
Expand Down
8 changes: 4 additions & 4 deletions core/core_bind.h
Original file line number Diff line number Diff line change
Expand Up @@ -390,8 +390,8 @@ class _File : public Reference {

void seek(int64_t p_position); // Seek to a given position.
void seek_end(int64_t p_position = 0); // Seek from the end of file.
int64_t get_position() const; // Get position in the file.
int64_t get_len() const; // Get size of the file.
uint64_t get_position() const; // Get position in the file.
uint64_t get_len() const; // Get size of the file.

bool eof_reached() const; // Reading passed EOF.

Expand All @@ -406,7 +406,7 @@ class _File : public Reference {

Variant get_var(bool p_allow_objects = false) const;

Vector<uint8_t> get_buffer(int p_length) const; // Get an array of bytes.
Vector<uint8_t> get_buffer(int64_t p_length) const; // Get an array of bytes.
String get_line() const;
Vector<String> get_csv_line(const String &p_delim = ",") const;
String get_as_text() const;
Expand Down Expand Up @@ -486,7 +486,7 @@ class _Directory : public Reference {
bool file_exists(String p_file);
bool dir_exists(String p_dir);

int get_space_left();
uint64_t get_space_left();

Error copy(String p_from, String p_to);
Error rename(String p_from, String p_to);
Expand Down
34 changes: 17 additions & 17 deletions core/io/file_access_compressed.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@

#include "core/string/print_string.h"

void FileAccessCompressed::configure(const String &p_magic, Compression::Mode p_mode, int p_block_size) {
void FileAccessCompressed::configure(const String &p_magic, Compression::Mode p_mode, uint32_t p_block_size) {
magic = p_magic.ascii().get_data();
if (magic.length() > 4) {
magic = magic.substr(0, 4);
Expand Down Expand Up @@ -67,10 +67,10 @@ Error FileAccessCompressed::open_after_magic(FileAccess *p_base) {
ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Can't open compressed file '" + p_base->get_path() + "' with block size 0, it is corrupted.");
}
read_total = f->get_32();
int bc = (read_total / block_size) + 1;
int acc_ofs = f->get_position() + bc * 4;
int max_bs = 0;
for (int i = 0; i < bc; i++) {
uint32_t bc = (read_total / block_size) + 1;
uint64_t acc_ofs = f->get_position() + bc * 4;
uint32_t max_bs = 0;
for (uint32_t i = 0; i < bc; i++) {
ReadBlock rb;
rb.offset = acc_ofs;
rb.csize = f->get_32();
Expand Down Expand Up @@ -148,15 +148,15 @@ void FileAccessCompressed::close() {
f->store_32(cmode); //write compression mode 4
f->store_32(block_size); //write block size 4
f->store_32(write_max); //max amount of data written 4
int bc = (write_max / block_size) + 1;
uint32_t bc = (write_max / block_size) + 1;

for (int i = 0; i < bc; i++) {
for (uint32_t i = 0; i < bc; i++) {
f->store_32(0); //compressed sizes, will update later
}

Vector<int> block_sizes;
for (int i = 0; i < bc; i++) {
int bl = i == (bc - 1) ? write_max % block_size : block_size;
for (uint32_t i = 0; i < bc; i++) {
uint32_t bl = i == (bc - 1) ? write_max % block_size : block_size;
uint8_t *bp = &write_ptr[i * block_size];

Vector<uint8_t> cblock;
Expand All @@ -168,7 +168,7 @@ void FileAccessCompressed::close() {
}

f->seek(16); //ok write block sizes
for (int i = 0; i < bc; i++) {
for (uint32_t i = 0; i < bc; i++) {
f->store_32(block_sizes[i]);
}
f->seek_end();
Expand All @@ -190,8 +190,9 @@ bool FileAccessCompressed::is_open() const {
return f != nullptr;
}

void FileAccessCompressed::seek(size_t p_position) {
void FileAccessCompressed::seek(uint64_t p_position) {
ERR_FAIL_COND_MSG(!f, "File must be opened before use.");

if (writing) {
ERR_FAIL_COND(p_position > write_max);

Expand All @@ -204,7 +205,7 @@ void FileAccessCompressed::seek(size_t p_position) {
} else {
at_end = false;
read_eof = false;
int block_idx = p_position / block_size;
uint32_t block_idx = p_position / block_size;
if (block_idx != read_block) {
read_block = block_idx;
f->seek(read_blocks[read_block].offset);
Expand All @@ -227,7 +228,7 @@ void FileAccessCompressed::seek_end(int64_t p_position) {
}
}

size_t FileAccessCompressed::get_position() const {
uint64_t FileAccessCompressed::get_position() const {
ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
if (writing) {
return write_pos;
Expand All @@ -236,7 +237,7 @@ size_t FileAccessCompressed::get_position() const {
}
}

size_t FileAccessCompressed::get_len() const {
uint64_t FileAccessCompressed::get_len() const {
ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
if (writing) {
return write_max;
Expand Down Expand Up @@ -285,9 +286,8 @@ uint8_t FileAccessCompressed::get_8() const {
return ret;
}

int FileAccessCompressed::get_buffer(uint8_t *p_dst, int p_length) const {
uint64_t FileAccessCompressed::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
ERR_FAIL_COND_V(p_length < 0, -1);
ERR_FAIL_COND_V_MSG(!f, -1, "File must be opened before use.");
ERR_FAIL_COND_V_MSG(writing, -1, "File has not been opened in read mode.");

Expand All @@ -296,7 +296,7 @@ int FileAccessCompressed::get_buffer(uint8_t *p_dst, int p_length) const {
return 0;
}

for (int i = 0; i < p_length; i++) {
for (uint64_t i = 0; i < p_length; i++) {
p_dst[i] = read_ptr[read_pos];
read_pos++;
if (read_pos >= read_block_size) {
Expand Down
28 changes: 14 additions & 14 deletions core/io/file_access_compressed.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,50 +37,50 @@
class FileAccessCompressed : public FileAccess {
Compression::Mode cmode = Compression::MODE_ZSTD;
bool writing = false;
uint32_t write_pos = 0;
uint64_t write_pos = 0;
uint8_t *write_ptr = nullptr;
uint32_t write_buffer_size = 0;
uint32_t write_max = 0;
uint64_t write_max = 0;
uint32_t block_size = 0;
mutable bool read_eof = false;
mutable bool at_end = false;

struct ReadBlock {
int csize;
int offset;
uint32_t csize;
uint64_t offset;
};

mutable Vector<uint8_t> comp_buffer;
uint8_t *read_ptr = nullptr;
mutable int read_block = 0;
int read_block_count = 0;
mutable int read_block_size = 0;
mutable int read_pos = 0;
mutable uint32_t read_block = 0;
uint32_t read_block_count = 0;
mutable uint32_t read_block_size = 0;
mutable uint64_t read_pos = 0;
Vector<ReadBlock> read_blocks;
uint32_t read_total = 0;
uint64_t read_total = 0;

String magic = "GCMP";
mutable Vector<uint8_t> buffer;
FileAccess *f = nullptr;

public:
void configure(const String &p_magic, Compression::Mode p_mode = Compression::MODE_ZSTD, int p_block_size = 4096);
void configure(const String &p_magic, Compression::Mode p_mode = Compression::MODE_ZSTD, uint32_t p_block_size = 4096);

Error open_after_magic(FileAccess *p_base);

virtual Error _open(const String &p_path, int p_mode_flags); ///< open a file
virtual void close(); ///< close a file
virtual bool is_open() const; ///< true when file is open

virtual void seek(size_t p_position); ///< seek to a given position
virtual void seek(uint64_t p_position); ///< seek to a given position
virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file
virtual size_t get_position() const; ///< get position in the file
virtual size_t get_len() const; ///< get size of the file
virtual uint64_t get_position() const; ///< get position in the file
virtual uint64_t get_len() const; ///< get size of the file

virtual bool eof_reached() const; ///< reading passed EOF

virtual uint8_t get_8() const; ///< get a byte
virtual int get_buffer(uint8_t *p_dst, int p_length) const;
virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const;

virtual Error get_error() const; ///< get last error

Expand Down
41 changes: 20 additions & 21 deletions core/io/file_access_encrypted.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,13 @@ Error FileAccessEncrypted::open_and_parse(FileAccess *p_base, const Vector<uint8

base = p_base->get_position();
ERR_FAIL_COND_V(p_base->get_len() < base + length, ERR_FILE_CORRUPT);
uint32_t ds = length;
uint64_t ds = length;
if (ds % 16) {
ds += 16 - (ds % 16);
}
data.resize(ds);

uint32_t blen = p_base->get_buffer(data.ptrw(), ds);
uint64_t blen = p_base->get_buffer(data.ptrw(), ds);
ERR_FAIL_COND_V(blen != ds, ERR_FILE_CORRUPT);

{
Expand Down Expand Up @@ -141,7 +141,7 @@ void FileAccessEncrypted::release() {
void FileAccessEncrypted::_release() {
if (writing) {
Vector<uint8_t> compressed;
size_t len = data.size();
uint64_t len = data.size();
if (len % 16) {
len += 16 - (len % 16);
}
Expand Down Expand Up @@ -198,24 +198,24 @@ String FileAccessEncrypted::get_path_absolute() const {
}
}

void FileAccessEncrypted::seek(size_t p_position) {
if (p_position > (size_t)data.size()) {
p_position = data.size();
void FileAccessEncrypted::seek(uint64_t p_position) {
if (p_position > get_len()) {
p_position = get_len();
}

pos = p_position;
eofed = false;
}

void FileAccessEncrypted::seek_end(int64_t p_position) {
seek(data.size() + p_position);
seek(get_len() + p_position);
}

size_t FileAccessEncrypted::get_position() const {
uint64_t FileAccessEncrypted::get_position() const {
return pos;
}

size_t FileAccessEncrypted::get_len() const {
uint64_t FileAccessEncrypted::get_len() const {
return data.size();
}

Expand All @@ -225,7 +225,7 @@ bool FileAccessEncrypted::eof_reached() const {

uint8_t FileAccessEncrypted::get_8() const {
ERR_FAIL_COND_V_MSG(writing, 0, "File has not been opened in read mode.");
if (pos >= data.size()) {
if (pos >= get_len()) {
eofed = true;
return 0;
}
Expand All @@ -235,13 +235,12 @@ uint8_t FileAccessEncrypted::get_8() const {
return b;
}

int FileAccessEncrypted::get_buffer(uint8_t *p_dst, int p_length) const {
uint64_t FileAccessEncrypted::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
ERR_FAIL_COND_V(p_length < 0, -1);
ERR_FAIL_COND_V_MSG(writing, -1, "File has not been opened in read mode.");

int to_copy = MIN(p_length, data.size() - pos);
for (int i = 0; i < to_copy; i++) {
uint64_t to_copy = MIN(p_length, get_len() - pos);
for (uint64_t i = 0; i < to_copy; i++) {
p_dst[i] = data[pos++];
}

Expand All @@ -256,16 +255,16 @@ Error FileAccessEncrypted::get_error() const {
return eofed ? ERR_FILE_EOF : OK;
}

void FileAccessEncrypted::store_buffer(const uint8_t *p_src, int p_length) {
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.");

if (pos < data.size()) {
for (int i = 0; i < p_length; i++) {
if (pos < get_len()) {
for (uint64_t i = 0; i < p_length; i++) {
store_8(p_src[i]);
}
} else if (pos == data.size()) {
} else if (pos == get_len()) {
data.resize(pos + p_length);
for (int i = 0; i < p_length; i++) {
for (uint64_t i = 0; i < p_length; i++) {
data.write[pos + i] = p_src[i];
}
pos += p_length;
Expand All @@ -281,10 +280,10 @@ void FileAccessEncrypted::flush() {
void FileAccessEncrypted::store_8(uint8_t p_dest) {
ERR_FAIL_COND_MSG(!writing, "File has not been opened in write mode.");

if (pos < data.size()) {
if (pos < get_len()) {
data.write[pos] = p_dest;
pos++;
} else if (pos == data.size()) {
} else if (pos == get_len()) {
data.push_back(p_dest);
pos++;
}
Expand Down
Loading

0 comments on commit 469fa47

Please sign in to comment.