#include "FileJsObject.hpp" #include #include #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(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(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(size)); // if we are in binary mode, read from the binary stream const auto data = this->_internal->read(static_cast(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(position)); return; } // if we are in binary mode, set the position of the raw binary stream this->_internal->seek(static_cast(position)); } void FileJsObject::close() const { // if still opened, close the file if (this->_internal->isOpen()) this->_internal->close(); }