diff options
Diffstat (limited to 'src/lib/corelib/jsextensions/textfile.cpp')
-rw-r--r-- | src/lib/corelib/jsextensions/textfile.cpp | 201 |
1 files changed, 92 insertions, 109 deletions
diff --git a/src/lib/corelib/jsextensions/textfile.cpp b/src/lib/corelib/jsextensions/textfile.cpp index 04d764377..c9f0edec9 100644 --- a/src/lib/corelib/jsextensions/textfile.cpp +++ b/src/lib/corelib/jsextensions/textfile.cpp @@ -37,13 +37,14 @@ ** ****************************************************************************/ +#include "jsextension.h" + #include <language/scriptengine.h> #include <logging/translator.h> #include <tools/hostosinfo.h> #include <QtCore/qfile.h> #include <QtCore/qfileinfo.h> -#include <QtCore/qobject.h> #include <QtCore/qtextstream.h> #include <QtCore/qvariant.h> @@ -53,16 +54,12 @@ #include <QtCore/qtextcodec.h> #endif -#include <QtScript/qscriptable.h> -#include <QtScript/qscriptengine.h> -#include <QtScript/qscriptvalue.h> - namespace qbs { namespace Internal { -class TextFile : public QObject, public QScriptable, public ResourceAcquiringScriptObject +class TextFile : public JsExtension<TextFile> { - Q_OBJECT + friend class JsExtension<TextFile>; public: enum OpenMode { @@ -71,77 +68,92 @@ public: ReadWrite = ReadOnly | WriteOnly, Append = 4 }; - Q_ENUM(OpenMode) - static QScriptValue ctor(QScriptContext *context, QScriptEngine *engine); - - Q_INVOKABLE void close(); - Q_INVOKABLE QString filePath(); - Q_INVOKABLE void setCodec(const QString &codec); - Q_INVOKABLE QString readLine(); - Q_INVOKABLE QString readAll(); - Q_INVOKABLE bool atEof() const; - Q_INVOKABLE void truncate(); - Q_INVOKABLE void write(const QString &str); - Q_INVOKABLE void writeLine(const QString &str); + static const char *name() { return "TextFile"; } + static void declareEnums(JSContext *ctx, JSValue classObj); + static JSValue ctor(JSContext *ctx, JSValueConst, JSValueConst, + int argc, JSValueConst *argv, int); + static void setupMethods(JSContext *ctx, JSValue obj); private: - TextFile(QScriptContext *context, const QString &filePath, OpenMode mode = ReadOnly, - const QString &codec = QLatin1String("UTF-8")); - - bool checkForClosed() const; - - // ResourceAcquiringScriptObject implementation - void releaseResources() override; + DEFINE_JS_FORWARDER(jsClose, &TextFile::close, "TextFile.close") + DEFINE_JS_FORWARDER(jsFilePath, &TextFile::filePath, "TextFile.filePath") + DEFINE_JS_FORWARDER(jsSetCodec, &TextFile::setCodec, "TextFile.setCodec") + DEFINE_JS_FORWARDER(jsReadLine, &TextFile::readLine, "TextFile.readLine") + DEFINE_JS_FORWARDER(jsReadAll, &TextFile::readAll, "TextFile.readAll") + DEFINE_JS_FORWARDER(jsAtEof, &TextFile::atEof, "TextFile.atEof") + DEFINE_JS_FORWARDER(jsTruncate, &TextFile::truncate, "TextFile.truncate") + DEFINE_JS_FORWARDER(jsWrite, &TextFile::write, "TextFile.write") + DEFINE_JS_FORWARDER(jsWriteLine, &TextFile::writeLine, "TextFile.writeLine") + + void close(); + QString filePath(); + void setCodec(const QString &codec); + QString readLine(); + QString readAll(); + bool atEof() const; + void truncate(); + void write(const QString &str); + void writeLine(const QString &str); + + TextFile(JSContext *, const QString &filePath, OpenMode mode, const QString &codec); + + void checkForClosed() const; std::unique_ptr<QFile> m_file; QTextCodec *m_codec = nullptr; }; -QScriptValue TextFile::ctor(QScriptContext *context, QScriptEngine *engine) +void TextFile::declareEnums(JSContext *ctx, JSValue classObj) { - TextFile *t; - switch (context->argumentCount()) { - case 0: - return context->throwError(Tr::tr("TextFile constructor needs path of file to be opened.")); - case 1: - t = new TextFile(context, context->argument(0).toString()); - break; - case 2: - t = new TextFile(context, - context->argument(0).toString(), - static_cast<OpenMode>(context->argument(1).toInt32()) - ); - break; - case 3: - t = new TextFile(context, - context->argument(0).toString(), - static_cast<OpenMode>(context->argument(1).toInt32()), - context->argument(2).toString() - ); - break; - default: - return context->throwError(Tr::tr("TextFile constructor takes at most three parameters.")); - } + DECLARE_ENUM(ctx, classObj, ReadOnly); + DECLARE_ENUM(ctx, classObj, WriteOnly); + DECLARE_ENUM(ctx, classObj, ReadWrite); + DECLARE_ENUM(ctx, classObj, Append); +} - const auto se = static_cast<ScriptEngine *>(engine); - se->addResourceAcquiringScriptObject(t); - const DubiousContextList dubiousContexts({ +JSValue TextFile::ctor(JSContext *ctx, JSValueConst, JSValueConst, + int argc, JSValueConst *argv, int) +{ + try { + const auto filePath = getArgument<QString>(ctx, "TextFile constructor", argc, argv); + OpenMode mode = ReadOnly; + QString codec = QLatin1String("UTF-8"); + if (argc > 1) { + mode = static_cast<OpenMode> + (fromArg<qint32>(ctx, "TextFile constructor", 2, argv[1])); + } + if (argc > 2) { + codec = fromArg<QString>(ctx, "TextFile constructor", 3, argv[2]); + } + ScopedJsValue obj(ctx, createObject(ctx, filePath, mode, codec)); + + const auto se = ScriptEngine::engineForContext(ctx); + const DubiousContextList dubiousContexts { DubiousContext(EvalContext::PropertyEvaluation, DubiousContext::SuggestMoving) - }); - se->checkContext(QStringLiteral("qbs.TextFile"), dubiousContexts); - se->setUsesIo(); - - return engine->newQObject(t, QScriptEngine::QtOwnership); + }; + se->checkContext(QStringLiteral("qbs.TextFile"), dubiousContexts); + se->setUsesIo(); + return obj.release(); + } catch (const QString &error) { return throwError(ctx, error); } } -TextFile::TextFile(QScriptContext *context, const QString &filePath, OpenMode mode, - const QString &codec) +void TextFile::setupMethods(JSContext *ctx, JSValue obj) { - Q_UNUSED(codec) - Q_ASSERT(thisObject().engine() == engine()); + setupMethod(ctx, obj, "close", &jsClose, 0); + setupMethod(ctx, obj, "filePath", &jsFilePath, 0); + setupMethod(ctx, obj, "atEof", &jsAtEof, 0); + setupMethod(ctx, obj, "setCodec", &jsSetCodec, 1); + setupMethod(ctx, obj, "readLine", &jsReadLine, 0); + setupMethod(ctx, obj, "readAll", &jsReadAll, 0); + setupMethod(ctx, obj, "truncate", &jsTruncate, 0); + setupMethod(ctx, obj, "write", &jsWrite, 1); + setupMethod(ctx, obj, "writeLine", &jsWriteLine, 1); +} - m_file = std::make_unique<QFile>(filePath); +TextFile::TextFile(JSContext *, const QString &filePath, OpenMode mode, const QString &codec) +{ + auto file = std::make_unique<QFile>(filePath); const auto newCodec = QTextCodec::codecForName(qPrintable(codec)); m_codec = newCodec ? newCodec : QTextCodec::codecForName("UTF-8"); QIODevice::OpenMode m = QIODevice::NotOpen; @@ -152,32 +164,27 @@ TextFile::TextFile(QScriptContext *context, const QString &filePath, OpenMode mo if (mode & Append) m |= QIODevice::Append; m |= QIODevice::Text; - if (Q_UNLIKELY(!m_file->open(m))) { - context->throwError(Tr::tr("Unable to open file '%1': %2") - .arg(filePath, m_file->errorString())); - m_file.reset(); - } + if (Q_UNLIKELY(!file->open(m))) + throw Tr::tr("Unable to open file '%1': %2").arg(filePath, file->errorString()); + m_file = std::move(file); } void TextFile::close() { - if (checkForClosed()) - return; + checkForClosed(); m_file->close(); m_file.reset(); } QString TextFile::filePath() { - if (checkForClosed()) - return {}; + checkForClosed(); return QFileInfo(*m_file).absoluteFilePath(); } void TextFile::setCodec(const QString &codec) { - if (checkForClosed()) - return; + checkForClosed(); const auto newCodec = QTextCodec::codecForName(qPrintable(codec)); if (newCodec) m_codec = newCodec; @@ -185,8 +192,7 @@ void TextFile::setCodec(const QString &codec) QString TextFile::readLine() { - if (checkForClosed()) - return {}; + checkForClosed(); auto result = m_codec->toUnicode(m_file->readLine()); if (!result.isEmpty() && result.back() == QLatin1Char('\n')) result.chop(1); @@ -195,68 +201,45 @@ QString TextFile::readLine() QString TextFile::readAll() { - if (checkForClosed()) - return {}; + checkForClosed(); return m_codec->toUnicode(m_file->readAll()); } bool TextFile::atEof() const { - if (checkForClosed()) - return true; + checkForClosed(); return m_file->atEnd(); } void TextFile::truncate() { - if (checkForClosed()) - return; + checkForClosed(); m_file->resize(0); } void TextFile::write(const QString &str) { - if (checkForClosed()) - return; + checkForClosed(); m_file->write(m_codec->fromUnicode(str)); } void TextFile::writeLine(const QString &str) { - if (checkForClosed()) - return; + checkForClosed(); m_file->write(m_codec->fromUnicode(str)); m_file->putChar('\n'); } -bool TextFile::checkForClosed() const +void TextFile::checkForClosed() const { - if (m_file) - return false; - QScriptContext *ctx = context(); - if (ctx) - ctx->throwError(Tr::tr("Access to TextFile object that was already closed.")); - return true; -} - -void TextFile::releaseResources() -{ - close(); - deleteLater(); + if (!m_file) + throw Tr::tr("Access to TextFile object that was already closed."); } } // namespace Internal } // namespace qbs -void initializeJsExtensionTextFile(QScriptValue extensionObject) +void initializeJsExtensionTextFile(qbs::Internal::ScriptEngine *engine, JSValue extensionObject) { - using namespace qbs::Internal; - QScriptEngine *engine = extensionObject.engine(); - QScriptValue obj = engine->newQMetaObject(&TextFile::staticMetaObject, - engine->newFunction(&TextFile::ctor)); - extensionObject.setProperty(QStringLiteral("TextFile"), obj); + qbs::Internal::TextFile::registerClass(engine, extensionObject); } - -Q_DECLARE_METATYPE(qbs::Internal::TextFile *) - -#include "textfile.moc" |