Skip to content

Commit

Permalink
64-bit sizes in IO
Browse files Browse the repository at this point in the history
  • Loading branch information
deathkiller committed Apr 25, 2024
1 parent 2cef5fd commit 2c49ff7
Show file tree
Hide file tree
Showing 17 changed files with 314 additions and 201 deletions.
67 changes: 38 additions & 29 deletions Sources/Shared/IO/AndroidAssetStream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,39 +53,47 @@ namespace Death { namespace IO {
#endif
}

std::int32_t AndroidAssetStream::Seek(std::int32_t offset, SeekOrigin origin)
std::int64_t AndroidAssetStream::Seek(std::int64_t offset, SeekOrigin origin)
{
std::int32_t seekValue = -1;
std::int64_t newPos = ErrorInvalidStream;
#if defined(DEATH_USE_FILE_DESCRIPTORS)
if (_fileDescriptor >= 0) {
switch (origin) {
case SeekOrigin::Begin: seekValue = ::lseek(_fileDescriptor, _startOffset + offset, SEEK_SET); break;
case SeekOrigin::Current: seekValue = ::lseek(_fileDescriptor, offset, SEEK_CUR); break;
case SeekOrigin::End: seekValue = ::lseek(_fileDescriptor, _startOffset + _size + offset, SEEK_END); break;
case SeekOrigin::Begin: newPos = ::lseek(_fileDescriptor, _startOffset + offset, SEEK_SET); break;
case SeekOrigin::Current: newPos = ::lseek(_fileDescriptor, offset, SEEK_CUR); break;
case SeekOrigin::End: newPos = ::lseek(_fileDescriptor, _startOffset + _size + offset, SEEK_END); break;
default: return ErrorInvalidParameter;
}
if (newPos >= _startOffset) {
newPos -= _startOffset;
} else if (newPos < 0) {
newPos = ErrorInvalidParameter;
}
seekValue -= _startOffset;
}
#else
if (_asset != nullptr) {
seekValue = AAsset_seek(_asset, offset, (std::int32_t)origin);
newPos = AAsset_seek64(_asset, offset, static_cast<std::int32_t>(origin));
if (newPos < 0) {
newPos = ErrorInvalidParameter;
}
}
#endif
return seekValue;
return newPos;
}

std::int32_t AndroidAssetStream::GetPosition() const
std::int64_t AndroidAssetStream::GetPosition() const
{
std::int32_t tellValue = -1;
std::int64_t pos = ErrorInvalidStream;
#if defined(DEATH_USE_FILE_DESCRIPTORS)
if (_fileDescriptor >= 0) {
tellValue = ::lseek(_fileDescriptor, 0L, SEEK_CUR) - _startOffset;
pos = ::lseek(_fileDescriptor, 0L, SEEK_CUR) - _startOffset;
}
#else
if (_asset != nullptr) {
tellValue = AAsset_seek(_asset, 0L, SEEK_CUR);
pos = AAsset_seek64(_asset, 0L, SEEK_CUR);
}
#endif
return tellValue;
return pos;
}

std::int32_t AndroidAssetStream::Read(void* buffer, std::int32_t bytes)
Expand All @@ -96,11 +104,11 @@ namespace Death { namespace IO {
#if defined(DEATH_USE_FILE_DESCRIPTORS)
if (_fileDescriptor >= 0) {
std::int32_t bytesToRead = bytes;
const std::int32_t seekValue = ::lseek(_fileDescriptor, 0L, SEEK_CUR);
if (seekValue >= _startOffset + _size) {
const std::int64_t pos = ::lseek(_fileDescriptor, 0L, SEEK_CUR);
if (pos >= _startOffset + _size) {
bytesToRead = 0; // Simulating EOF
} else if (seekValue + static_cast<std::int32_t>(bytes) > _startOffset + _size) {
bytesToRead = (_startOffset + _size) - seekValue;
} else if (pos + bytes > _startOffset + _size) {
bytesToRead = (_startOffset + _size) - pos;
}
bytesRead = ::read(_fileDescriptor, buffer, bytesToRead);
}
Expand All @@ -114,10 +122,11 @@ namespace Death { namespace IO {

std::int32_t AndroidAssetStream::Write(const void* buffer, std::int32_t bytes)
{
return 0;
// Not supported
return ErrorInvalidStream;
}

bool AndroidAssetStream::IsValid() const
bool AndroidAssetStream::IsValid()
{
#if defined(DEATH_USE_FILE_DESCRIPTORS)
return (_fileDescriptor >= 0);
Expand All @@ -142,7 +151,7 @@ namespace Death { namespace IO {
DEATH_ASSERT(path != nullptr, nullptr, "path is nullptr");
if (strncmp(path, Prefix.data(), Prefix.size()) == 0) {
// Skip leading path separator character
return (path[7] == '/' ? path + 8 : path + 7);
return (path[7] == '/' || path[7] == '\\' ? path + 8 : path + 7);
}
return nullptr;
}
Expand Down Expand Up @@ -193,19 +202,19 @@ namespace Death { namespace IO {
return false;
}

off_t AndroidAssetStream::GetLength(const char* path)
std::int64_t AndroidAssetStream::GetFileSize(const char* path)
{
DEATH_ASSERT(path != nullptr, 0, "path is nullptr");

off_t assetLength = 0;
off64_t assetLength = 0;
const char* strippedPath = TryGetAssetPath(path);
if (strippedPath == nullptr) {
return assetLength;
}

AAsset* asset = AAssetManager_open(_assetManager, strippedPath, AASSET_MODE_UNKNOWN);
if (asset != nullptr) {
assetLength = AAsset_getLength(asset);
assetLength = AAsset_getLength64(asset);
AAsset_close(asset);
}

Expand Down Expand Up @@ -243,15 +252,15 @@ namespace Death { namespace IO {

#if defined(DEATH_USE_FILE_DESCRIPTORS)
// An asset file can only be read
AAsset* asset = AAssetManager_open(_assetManager, _path.data(), AASSET_MODE_UNKNOWN);
AAsset* asset = AAssetManager_open(_assetManager, _path.data(), AASSET_MODE_RANDOM);
if (asset == nullptr) {
LOGE("Cannot open file \"%s\"", _path.data());
return;
}

off_t outStart = 0;
off_t outLength = 0;
_fileDescriptor = AAsset_openFileDescriptor(asset, &outStart, &outLength);
off64_t outStart = 0;
off64_t outLength = 0;
_fileDescriptor = AAsset_openFileDescriptor64(asset, &outStart, &outLength);
_startOffset = outStart;
_size = outLength;

Expand All @@ -267,7 +276,7 @@ namespace Death { namespace IO {
LOGI("File \"%s\" opened", _path.data());
#else
// An asset file can only be read
_asset = AAssetManager_open(_assetManager, _path.data(), AASSET_MODE_UNKNOWN);
_asset = AAssetManager_open(_assetManager, _path.data(), AASSET_MODE_RANDOM);
if (_asset == nullptr) {
LOGE("Cannot open file \"%s\"", _path.data());
return;
Expand All @@ -276,7 +285,7 @@ namespace Death { namespace IO {
LOGI("File \"%s\" opened", _path.data());

// Calculating file size
_size = AAsset_getLength(_asset);
_size = AAsset_getLength64(_asset);
#endif
}

Expand Down
10 changes: 5 additions & 5 deletions Sources/Shared/IO/AndroidAssetStream.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,18 @@ namespace Death { namespace IO {
class AndroidAssetStream : public Stream
{
public:
static constexpr Containers::StringView Prefix = "asset:/"_s;
static constexpr Containers::StringView Prefix = "asset:"_s;

AndroidAssetStream(const Containers::String& path, FileAccessMode mode);
~AndroidAssetStream() override;

void Close() override;
std::int32_t Seek(std::int32_t offset, SeekOrigin origin) override;
std::int32_t GetPosition() const override;
std::int64_t Seek(std::int64_t offset, SeekOrigin origin) override;
std::int64_t GetPosition() const override;
std::int32_t Read(void* buffer, std::int32_t bytes) override;
std::int32_t Write(const void* buffer, std::int32_t bytes) override;

bool IsValid() const override;
bool IsValid() override;

/** @brief Returns file path */
Containers::StringView GetPath() const;
Expand Down Expand Up @@ -67,7 +67,7 @@ namespace Death { namespace IO {
/** @brief Checks if an asset path exists and can be opened as a directory */
static bool TryOpenDirectory(const char* path);
/** @brief Returns the total size of the asset data */
static off_t GetLength(const char* path);
static std::int64_t GetFileSize(const char* path);

static AAssetDir* OpenDirectory(const char* dirName);
static void CloseDirectory(AAssetDir* assetDir);
Expand Down
83 changes: 51 additions & 32 deletions Sources/Shared/IO/DeflateStream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ namespace Death { namespace IO {
DeflateStream::DeflateStream()
: _inputStream(nullptr), _inputSize(-1), _state(State::Unknown)
{
_size = ErrorInvalidStream;
}

DeflateStream::DeflateStream(Stream& inputStream, std::int32_t inputSize, bool rawInflate)
Expand All @@ -36,29 +37,32 @@ namespace Death { namespace IO {
Close();
}

std::int32_t DeflateStream::Seek(std::int32_t offset, SeekOrigin origin)
std::int64_t DeflateStream::Seek(std::int64_t offset, SeekOrigin origin)
{
switch (origin) {
case SeekOrigin::Current: {
DEATH_ASSERT(offset >= 0, -1, "Cannot seek to negative values");
DEATH_ASSERT(offset >= 0, ErrorInvalidParameter, "Cannot seek to negative values");

char buffer[4096];
while (offset > 0) {
std::int32_t size = (offset > sizeof(buffer) ? sizeof(buffer) : offset);
Read(buffer, size);
offset -= size;
std::int32_t size = (offset > sizeof(buffer) ? sizeof(buffer) : static_cast<std::int32_t>(offset));
std::int32_t bytesRead = Read(buffer, size);
if (bytesRead <= 0) {
return bytesRead;
}
offset -= bytesRead;
}

return static_cast<std::int32_t>(_strm.total_out);
return static_cast<std::int64_t>(_strm.total_out);
}
}

return NotSeekable;
return ErrorInvalidParameter;
}

std::int32_t DeflateStream::GetPosition() const
std::int64_t DeflateStream::GetPosition() const
{
return static_cast<std::int32_t>(_strm.total_out);
return static_cast<std::int64_t>(_strm.total_out);
}

std::int32_t DeflateStream::Read(void* buffer, std::int32_t bytes)
Expand All @@ -80,11 +84,14 @@ namespace Death { namespace IO {
std::int32_t DeflateStream::Write(const void* buffer, std::int32_t bytes)
{
// Not supported
return -1;
return ErrorInvalidStream;
}

bool DeflateStream::IsValid() const
bool DeflateStream::IsValid()
{
if (_state == State::Created) {
InitializeInternal();
}
return (_state == State::Initialized || _state == State::Finished);
}

Expand All @@ -96,7 +103,7 @@ namespace Death { namespace IO {
_inputSize = inputSize;
_state = State::Created;
_rawInflate = rawInflate;
_size = INT32_MAX;
_size = ErrorNotSeekable;

_strm.zalloc = Z_NULL;
_strm.zfree = Z_NULL;
Expand All @@ -111,23 +118,32 @@ namespace Death { namespace IO {
CeaseReading();
_inputStream = nullptr;
_state = State::Unknown;
_size = 0;
_size = ErrorInvalidStream;
}

void DeflateStream::InitializeInternal()
{
std::int32_t error = (_rawInflate ? inflateInit2(&_strm, -MAX_WBITS) : inflateInit(&_strm));
if (error != Z_OK) {
_state = State::Failed;
LOGE("Failed to initialize compressed stream with error: %i", error);
return;
}

_state = State::Initialized;
}

std::int32_t DeflateStream::ReadInternal(void* ptr, std::int32_t size)
{
if (size == 0 || _state == State::Unknown || _state >= State::Finished) {
if (size == 0) {
return 0;
}

if (_state == State::Created) {
std::int32_t error = (_rawInflate ? inflateInit2(&_strm, -MAX_WBITS) : inflateInit(&_strm));
if (error != Z_OK) {
_state = State::Failed;
LOGE("Failed to initialize compressed stream with error: %i", error);
return -1;
}
_state = State::Initialized;
InitializeInternal();
}
if (_state == State::Unknown || _state >= State::Finished) {
return ErrorInvalidStream;
}

if (_strm.avail_in == 0) {
Expand Down Expand Up @@ -187,6 +203,8 @@ namespace Death { namespace IO {
DeflateWriter::DeflateWriter(Stream& outputStream, std::int32_t compressionLevel, bool rawInflate)
: _outputStream(&outputStream), _state(State::Created)
{
_size = ErrorNotSeekable;

_strm.zalloc = Z_NULL;
_strm.zfree = Z_NULL;
_strm.opaque = Z_NULL;
Expand Down Expand Up @@ -223,32 +241,33 @@ namespace Death { namespace IO {
_state = State::Finished;
}

std::int32_t DeflateWriter::Seek(std::int32_t offset, SeekOrigin origin)
std::int64_t DeflateWriter::Seek(std::int64_t offset, SeekOrigin origin)
{
return NotSeekable;
return ErrorNotSeekable;
}

std::int32_t DeflateWriter::GetPosition() const
std::int64_t DeflateWriter::GetPosition() const
{
return NotSeekable;
return ErrorNotSeekable;
}

std::int32_t DeflateWriter::Read(void* buffer, std::int32_t bytes)
{
return 0;
// Not supported
return ErrorInvalidStream;
}

std::int32_t DeflateWriter::Write(const void* buffer, std::int32_t bytes)
{
if (_state != State::Created && _state != State::Initialized) {
return 0;
return ErrorInvalidStream;
}

_state = State::Initialized;
return WriteInternal(buffer, bytes, false);
}

bool DeflateWriter::IsValid() const
bool DeflateWriter::IsValid()
{
return(_state != State::Failed && _outputStream->IsValid());
}
Expand Down Expand Up @@ -283,11 +302,11 @@ namespace Death { namespace IO {
return bytes - (std::int32_t)_strm.avail_in;
}

std::int32_t DeflateWriter::GetMaxDeflatedSize(int32_t uncompressedSize)
std::int64_t DeflateWriter::GetMaxDeflatedSize(std::int64_t uncompressedSize)
{
constexpr std::int32_t MinBlockSize = 5000;
std::int32_t max_blocks = std::max((uncompressedSize + MinBlockSize - 1) / MinBlockSize, 1);
return uncompressedSize + (5 * max_blocks) + 1 + 8;
constexpr std::int64_t MinBlockSize = 5000;
std::int64_t maxBlocks = std::max((uncompressedSize + MinBlockSize - 1) / MinBlockSize, 1LL);
return uncompressedSize + (5 * maxBlocks) + 1 + 8;
}

}}
Expand Down
Loading

0 comments on commit 2c49ff7

Please sign in to comment.