Atlas-Launcher/source/javascript/module/file_system/object/FileJsObject.cpp

103 lines
3.4 KiB
C++

#include "FileJsObject.hpp"
#include <QJSValue>
#include <QTextStream>
#include "exception/FileNotFoundException.hpp"
#include "javascript/engine/AtlasJsEngine.hpp"
#include "utils/qt/fileOpenMode.hpp"
FileJsObject::FileJsObject(AtlasJsEngine* engine, const std::filesystem::path& virtualPath) {
// save the engine
this->engine = engine;
// create the internal QFile
std::filesystem::path realPath;
try {
realPath = this->engine->getFileSystem().resolve(virtualPath);
} catch (const vfs::exception::FileNotFoundException& exception) {
this->engine->throwError(QJSValue::ErrorType::URIError, "Invalid path.");
return;
}
// allocate the internal file
this->_internal = std::make_unique<QFile>(realPath);
}
void FileJsObject::open(const QString& mode) {
// get the mode flags from its string representation
this->mode = fileModeFromString(mode);
// open the file with the corresponding mode
if (!this->_internal->open(this->mode)) {
this->engine->throwError(QJSValue::URIError, "Cannot open the file.");
return;
}
// if we are in text mode, prepare the QTextStream wrapper
if (this->mode.testFlag(QIODevice::Text))
this->textStream = std::make_unique<QTextStream>(this->_internal.get());
}
QJSValue FileJsObject::read(const std::size_t size) const {
// check if we can read the file
if (!this->mode.testFlag(QIODevice::ReadOnly)) {
this->engine->throwError(QJSValue::ErrorType::TypeError, "The file is not open in read mode.");
return QJSValue(QJSPrimitiveNull());
}
// if we are in text mode, read from the text stream
if (this->mode.testFlag(QIODevice::Text))
return this->textStream->read(static_cast<qint64>(size));
// if we are in binary mode, read from the binary stream
const auto data = this->_internal->read(static_cast<qint64>(size));
return this->engine->toScriptValue(data);
}
std::size_t FileJsObject::write(const QJSValue& data) const {
// check if we can write into the file
if (!this->mode.testFlag(QIODevice::WriteOnly)) {
this->engine->throwError(QJSValue::ErrorType::TypeError, "The file is not open in write mode.");
return 0;
}
const QString dataString = data.toString();
// if we are in text mode, write text data
if (this->mode.testFlag(QIODevice::Text)) {
*this->textStream << dataString;
return dataString.size();
}
const QByteArray dataByte = dataString.toUtf8();
// if we are in binary mode, insert the raw binary data
return this->_internal->write(dataByte);
}
std::size_t FileJsObject::tell() const {
// if we are in text mode, return the position of the text stream
if (this->mode.testFlag(QIODevice::Text))
return this->textStream->pos();
// if we are in binary mode, return the position of the raw binary stream
return this->_internal->pos();
}
void FileJsObject::seek(const std::size_t position) const {
// if we are in text mode, set the position of the text stream
if (this->mode.testFlag(QIODevice::Text)) {
this->textStream->seek(static_cast<qint64>(position));
return;
}
// if we are in binary mode, set the position of the raw binary stream
this->_internal->seek(static_cast<qint64>(position));
}
void FileJsObject::close() const {
// if still opened, close the file
if (this->_internal->isOpen())
this->_internal->close();
}