feat: 完善脚本的宏支持;
This commit is contained in:
parent
06f48375cf
commit
80691396f3
|
@ -777,19 +777,6 @@ bool QEditor::save(const QString &fn) {
|
|||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
void QEditor::checkClipboard() {
|
||||
// LOOKS LIKE THIS FUNCTION NEVER GETS CALLED DESPITE THE CONNECTION...
|
||||
|
||||
// const QMimeData *d = QApplication::clipboard()->mimeData();
|
||||
|
||||
// qDebug("checking clipboard : %s", d);
|
||||
|
||||
// QCE_ENABLE_ACTION("paste", d && d->hasText())
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
|
|
|
@ -310,7 +310,6 @@ signals:
|
|||
void inputTimeOuted();
|
||||
|
||||
public slots:
|
||||
void checkClipboard();
|
||||
void reconnectWatcher();
|
||||
void fileChanged(const QString &f);
|
||||
|
||||
|
|
|
@ -88,8 +88,6 @@ set(ANGEL_SCRIPT_ADDON
|
|||
${ANGEL_SCRIPT_ADDON_ROOT}/scriptany/scriptany.h
|
||||
${ANGEL_SCRIPT_ADDON_ROOT}/scriptarray/scriptarray.cpp
|
||||
${ANGEL_SCRIPT_ADDON_ROOT}/scriptarray/scriptarray.h
|
||||
${ANGEL_SCRIPT_ADDON_ROOT}/scriptfile/scriptfile.cpp
|
||||
${ANGEL_SCRIPT_ADDON_ROOT}/scriptfile/scriptfile.h
|
||||
${ANGEL_SCRIPT_ADDON_ROOT}/scriptgrid/scriptgrid.cpp
|
||||
${ANGEL_SCRIPT_ADDON_ROOT}/scriptgrid/scriptgrid.h
|
||||
${ANGEL_SCRIPT_ADDON_ROOT}/scripthandle/scripthandle.cpp
|
||||
|
@ -334,7 +332,10 @@ set(SCRIPT_ADDON_SRC
|
|||
src/scriptaddon/scriptregex.cpp
|
||||
src/scriptaddon/scriptcolor.h
|
||||
src/scriptaddon/scriptcolor.cpp
|
||||
src/scriptaddon/scriptjson.h src/scriptaddon/scriptjson.cpp)
|
||||
src/scriptaddon/scriptjson.h
|
||||
src/scriptaddon/scriptjson.cpp
|
||||
src/scriptaddon/scriptfile.cpp
|
||||
src/scriptaddon/scriptfile.h)
|
||||
|
||||
set(CODEEDIT_WIDGET
|
||||
src/qcodeeditwidget/qgotolinepanel.h
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -68,9 +68,8 @@ AppManager::AppManager(int &argc, char *argv[])
|
|||
throw CrashCode::GenericCallNotSupported;
|
||||
}
|
||||
|
||||
Logger::instance();
|
||||
|
||||
auto &set = SettingManager::instance();
|
||||
Logger::instance();
|
||||
QFont font(set.appFontFamily(), set.appfontSize());
|
||||
setFont(font);
|
||||
|
||||
|
|
|
@ -99,6 +99,10 @@ void AsCompletion::complete(const QDocumentCursor &c, const QString &trigger) {
|
|||
off = cur.columnNumber();
|
||||
}
|
||||
} else {
|
||||
// TODO: PRs are welcomed !!!
|
||||
// If this software is well-known or brings me lots of
|
||||
// financial support, I will implement it myself.
|
||||
|
||||
// parse current code
|
||||
// auto codes = c.document()->text(true, false);
|
||||
// parser.parse(codes, this->editor()->fileName());
|
||||
|
|
|
@ -20,6 +20,13 @@
|
|||
#include <QDir>
|
||||
#include <QFileInfo>
|
||||
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(
|
||||
QStringList, DEFAULT_MARCO,
|
||||
({"__AS_ARRAY__", "__AS_ANY__", "__AS_GRID__", "__AS_HANDLE__",
|
||||
"__AS_MATH__", "__AS_WEAKREF__", "__AS_COROUTINE__", "__WING_FILE__",
|
||||
"__WING_STRING__", "__WING_COLOR__", "__WING_JSON__", "__WING_REGEX__",
|
||||
"__WING_DICTIONARY__"}));
|
||||
|
||||
AsPreprocesser::AsPreprocesser(asIScriptEngine *engine) : engine(engine) {
|
||||
Q_ASSERT(engine);
|
||||
|
||||
|
@ -28,6 +35,8 @@ AsPreprocesser::AsPreprocesser(asIScriptEngine *engine) : engine(engine) {
|
|||
|
||||
pragmaCallback = nullptr;
|
||||
pragmaParam = nullptr;
|
||||
|
||||
definedWords = *DEFAULT_MARCO;
|
||||
}
|
||||
|
||||
AsPreprocesser::~AsPreprocesser() { void ClearAll(); }
|
||||
|
|
|
@ -124,9 +124,9 @@ protected:
|
|||
PRAGMACALLBACK_t pragmaCallback;
|
||||
void *pragmaParam;
|
||||
|
||||
QVector<QString> includedScripts;
|
||||
QStringList includedScripts;
|
||||
|
||||
QVector<QString> definedWords;
|
||||
QStringList definedWords;
|
||||
};
|
||||
|
||||
#endif // ASPREPROCESSER_H
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#ifndef CLICKCALLBACK_H
|
||||
#define CLICKCALLBACK_H
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ QAsCodeParser::SymbolTable QAsCodeParser::parse(const QByteArray &codes) {
|
|||
fn.name = v.name;
|
||||
fn.nameInSrc = v.nameInSrc;
|
||||
fn.content = v.args;
|
||||
fn.ns = v.ns;
|
||||
// fn.ns = v.ns;
|
||||
fn.typeStr = v.ret;
|
||||
ret.insert(p->first, fn);
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ QAsCodeParser::SymbolTable QAsCodeParser::parseIntell(qsizetype offset,
|
|||
|
||||
SymbolTable ret;
|
||||
auto pend = _symtable.lowerBound(offset);
|
||||
for (auto p = _symtable.cbegin(); p != pend; p++) {
|
||||
for (auto p = _symtable.begin(); p != pend; p++) {
|
||||
ret.insert(p.key(), p.value());
|
||||
}
|
||||
|
||||
|
@ -80,7 +80,7 @@ QAsCodeParser::SymbolTable QAsCodeParser::parseIntell(qsizetype offset,
|
|||
// you can extend it with more features
|
||||
// PRS are welcomed.
|
||||
auto pend = m_segs.lowerBound(offset);
|
||||
for (auto p = m_segs.cbegin(); p != pend; ++p) {
|
||||
for (auto p = m_segs.begin(); p != pend; ++p) {
|
||||
auto v = p.value();
|
||||
|
||||
Symbol fn;
|
||||
|
@ -88,7 +88,7 @@ QAsCodeParser::SymbolTable QAsCodeParser::parseIntell(qsizetype offset,
|
|||
fn.name = v.name;
|
||||
fn.nameInSrc = v.nameInSrc;
|
||||
fn.content = v.args;
|
||||
fn.ns = v.ns;
|
||||
// fn.ns = v.ns;
|
||||
fn.typeStr = v.ret;
|
||||
ret.insert(p.key(), fn);
|
||||
}
|
||||
|
@ -192,7 +192,7 @@ QAsCodeParser::Symbol QAsCodeParser::ParseFunctionDefinition() {
|
|||
se.name = getSymbolString(id);
|
||||
se.nameInSrc = id.pos;
|
||||
se.content = params;
|
||||
se.ns = getRealNamespace(ns);
|
||||
// se.ns = getRealNamespace(ns);
|
||||
|
||||
// Parse an optional 'const' after the function definition (used for
|
||||
// object methods)
|
||||
|
@ -1481,11 +1481,11 @@ QByteArray QAsCodeParser::getSymbolString(const sToken &t) {
|
|||
}
|
||||
|
||||
QByteArrayList QAsCodeParser::getRealNamespace(const QByteArrayList &ns) {
|
||||
if (ns.isEmpty()) {
|
||||
return _curns + ns;
|
||||
} else {
|
||||
return ns;
|
||||
}
|
||||
// if (ns.isEmpty()) {
|
||||
// return _curns + ns;
|
||||
// } else {
|
||||
return ns;
|
||||
// }
|
||||
}
|
||||
|
||||
void QAsCodeParser::ParseNamespace() {
|
||||
|
@ -1496,15 +1496,14 @@ void QAsCodeParser::ParseNamespace() {
|
|||
RewindErrorTo(&t1);
|
||||
}
|
||||
|
||||
auto iden = ParseIdentifier();
|
||||
ParseIdentifier();
|
||||
if (isSyntaxError)
|
||||
return;
|
||||
|
||||
GetToken(&t1);
|
||||
while (t1.type == ttScope) {
|
||||
ParseIdentifier();
|
||||
|
||||
// NOTE
|
||||
auto id = ParseIdentifier();
|
||||
if (isSyntaxError)
|
||||
return;
|
||||
|
||||
|
@ -1518,8 +1517,6 @@ void QAsCodeParser::ParseNamespace() {
|
|||
|
||||
sToken start = t1;
|
||||
|
||||
_curns.append(QByteArray(t1.pos, t1.length));
|
||||
|
||||
ParseScript(true);
|
||||
|
||||
if (!isSyntaxError) {
|
||||
|
@ -1538,8 +1535,6 @@ QAsCodeParser::CodeSegment QAsCodeParser::ParseFunction(bool isMethod) {
|
|||
sToken t1;
|
||||
GetToken(&t1);
|
||||
|
||||
auto tstart = t1;
|
||||
|
||||
if (!isMethod) {
|
||||
// A global function can be marked as shared and external
|
||||
while (t1.type == ttIdentifier) {
|
||||
|
@ -1624,14 +1619,14 @@ QAsCodeParser::CodeSegment QAsCodeParser::ParseFunction(bool isMethod) {
|
|||
RewindTo(&t1);
|
||||
if (t1.type == ttEndStatement) {
|
||||
ParseToken(ttEndStatement);
|
||||
fn.ns = _curns;
|
||||
// fn.ns = _curns;
|
||||
return fn;
|
||||
}
|
||||
|
||||
// We should just find the end of the statement block here. The statements
|
||||
// will be parsed on request by the compiler once it starts the compilation.
|
||||
SuperficiallyParseStatementBlock();
|
||||
fn.ns = _curns;
|
||||
// fn.ns = _curns;
|
||||
fn.code = code.mid(t1.pos, sourcePos - t1.pos);
|
||||
fn.valid = true;
|
||||
return fn;
|
||||
|
@ -1639,7 +1634,6 @@ QAsCodeParser::CodeSegment QAsCodeParser::ParseFunction(bool isMethod) {
|
|||
|
||||
QAsCodeParser::Symbol QAsCodeParser::ParseFuncDef() {
|
||||
Symbol sym;
|
||||
size_t eoff;
|
||||
|
||||
// Allow keywords 'external' and 'shared' before 'interface'
|
||||
sToken t1;
|
||||
|
@ -1718,6 +1712,7 @@ void QAsCodeParser::ParseClass() {
|
|||
auto cls = ParseIdentifier();
|
||||
clssym.name = getSymbolString(cls);
|
||||
clssym.nameInSrc = cls.pos;
|
||||
clssym.type = SymbolType::Class;
|
||||
|
||||
// External shared declarations are ended with ';'
|
||||
GetToken(&t);
|
||||
|
@ -1789,6 +1784,8 @@ void QAsCodeParser::ParseClass() {
|
|||
RewindErrorTo(&t);
|
||||
return;
|
||||
}
|
||||
|
||||
_symtable.insert(cls.pos, clssym);
|
||||
}
|
||||
|
||||
void QAsCodeParser::ParseMixin() {
|
||||
|
@ -1877,7 +1874,7 @@ void QAsCodeParser::ParseInitList() {
|
|||
|
||||
void QAsCodeParser::ParseInterface() {
|
||||
Symbol sym;
|
||||
size_t eoff;
|
||||
|
||||
sToken t;
|
||||
|
||||
// Allow keywords 'external' and 'shared' before 'interface'
|
||||
|
@ -2149,7 +2146,7 @@ void QAsCodeParser::ParseEnumeration() {
|
|||
sym.name = getSymbolString(token);
|
||||
sym.nameInSrc = token.pos;
|
||||
sym.type = SymbolType::Enum;
|
||||
sym.ns = _curns;
|
||||
// sym.ns = _curns;
|
||||
|
||||
// External shared declarations are ended with ';'
|
||||
GetToken(&token);
|
||||
|
@ -2254,7 +2251,7 @@ void QAsCodeParser::ParseTypedef() {
|
|||
st.name = getSymbolString(r);
|
||||
|
||||
sym.content.append(st);
|
||||
sym.ns = _curns;
|
||||
// sym.ns = _curns;
|
||||
|
||||
_symtable.insert(eoff, sym);
|
||||
}
|
||||
|
@ -3251,6 +3248,7 @@ bool QAsCodeParser::IsAssignOperator(int tokenType) {
|
|||
}
|
||||
|
||||
bool QAsCodeParser::DoesTypeExist(const QString &t) {
|
||||
Q_UNUSED(t);
|
||||
// TODO: don't check
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -51,15 +51,14 @@ public:
|
|||
Invalid,
|
||||
FnDecl,
|
||||
Import,
|
||||
Value, // a common value
|
||||
Variable, // a variable
|
||||
Enum, // an enum
|
||||
Class, // a class type
|
||||
Namespace, // a namespace
|
||||
Function, // a function
|
||||
TypeDef, // a typedef
|
||||
FnDef, // a funcdef
|
||||
Property, // a property
|
||||
Value, // a common value
|
||||
Variable, // a variable
|
||||
Enum, // an enum
|
||||
Class, // a class type
|
||||
Function, // a function
|
||||
TypeDef, // a typedef
|
||||
FnDef, // a funcdef
|
||||
Property, // a property
|
||||
};
|
||||
|
||||
enum class Visiblity { Public, Private, Protected };
|
||||
|
@ -68,7 +67,7 @@ public:
|
|||
|
||||
struct CodeSegment {
|
||||
bool valid = false;
|
||||
QByteArrayList ns;
|
||||
// QByteArrayList ns;
|
||||
QByteArray ret;
|
||||
QByteArray name;
|
||||
qsizetype nameInSrc = -1;
|
||||
|
@ -86,7 +85,7 @@ public:
|
|||
Visiblity vis = Visiblity::Public;
|
||||
QList<Symbol> content;
|
||||
|
||||
QByteArrayList ns; // namespaces
|
||||
// QByteArrayList ns; // namespaces
|
||||
QMap<qsizetype, CodeSegment> codesegs; // used in class
|
||||
|
||||
// size_t scope = 0; // 0 for all
|
||||
|
@ -231,7 +230,6 @@ private:
|
|||
|
||||
asCScriptEngine *engine;
|
||||
|
||||
QByteArrayList _curns; // current namespaces
|
||||
// size_t _curscope = 0;
|
||||
SymbolTable _symtable;
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "define.h"
|
||||
#include "plugin/pluginsystem.h"
|
||||
#include "scriptaddon/scriptcolor.h"
|
||||
#include "scriptaddon/scriptfile.h"
|
||||
#include "scriptaddon/scriptjson.h"
|
||||
#include "scriptaddon/scriptqstring.h"
|
||||
#include "scriptaddon/scriptregex.h"
|
||||
|
@ -136,22 +137,9 @@ bool ScriptMachine::configureEngine(asIScriptEngine *engine) {
|
|||
}
|
||||
|
||||
r = engine->RegisterGlobalFunction(
|
||||
"int exec(const string &in exe, const string &in params)",
|
||||
asFUNCTIONPR(execSystemCmd, (const std::string &, const std::string &),
|
||||
int),
|
||||
asCALL_CDECL);
|
||||
Q_ASSERT(r >= 0);
|
||||
if (r < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
r = engine->RegisterGlobalFunction(
|
||||
"int exec(const string &in exe, const string &in params, "
|
||||
"string &out output)",
|
||||
asFUNCTIONPR(execSystemCmd,
|
||||
(const std::string &, const std::string &, std::string &),
|
||||
int),
|
||||
asCALL_CDECL);
|
||||
"int exec(string &out output, const string &in exe, "
|
||||
"const string &in params = \"\", int timeout = 3000)",
|
||||
asFUNCTION(execSystemCmd), asCALL_CDECL);
|
||||
Q_ASSERT(r >= 0);
|
||||
if (r < 0) {
|
||||
return false;
|
||||
|
@ -246,23 +234,27 @@ bool ScriptMachine::isType(asITypeInfo *tinfo, RegisteredType type) {
|
|||
return tinfo->DerivesFrom(t) || tinfo->Implements(t);
|
||||
}
|
||||
|
||||
int ScriptMachine::execSystemCmd(const std::string &exe,
|
||||
const std::string ¶ms, std::string &out) {
|
||||
int ScriptMachine::execSystemCmd(QString &out, const QString &exe,
|
||||
const QString ¶ms, int timeout) {
|
||||
if (Utilities::isRoot()) {
|
||||
auto ctx = asGetActiveContext();
|
||||
if (ctx) {
|
||||
auto err = tr("ExecNotAllowedInRoot");
|
||||
ctx->SetException(err.toUtf8());
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
QProcess ps;
|
||||
ps.setProgram(QString::fromStdString(exe));
|
||||
ps.setArguments(QProcess::splitCommand(QString::fromStdString(params)));
|
||||
ps.setProgram(exe);
|
||||
ps.setArguments(QProcess::splitCommand(params));
|
||||
ps.start();
|
||||
ps.waitForFinished(-1);
|
||||
auto r = ps.readAllStandardOutput();
|
||||
out = r.toStdString();
|
||||
return ps.exitCode();
|
||||
}
|
||||
|
||||
int ScriptMachine::execSystemCmd(const std::string &exe,
|
||||
const std::string ¶ms) {
|
||||
return QProcess::execute(
|
||||
QString::fromStdString(exe),
|
||||
QProcess::splitCommand(QString::fromStdString(params)));
|
||||
if (ps.waitForFinished(timeout)) {
|
||||
out = ps.readAllStandardOutput();
|
||||
return ps.exitCode();
|
||||
} else {
|
||||
ps.kill();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
bool ScriptMachine::executeScript(const QString &script, bool isInDebug) {
|
||||
|
@ -272,6 +264,9 @@ bool ScriptMachine::executeScript(const QString &script, bool isInDebug) {
|
|||
setDebugMode(isInDebug);
|
||||
|
||||
asBuilder builder(_engine);
|
||||
for (auto &m : PluginSystem::instance().scriptMarcos()) {
|
||||
builder.DefineWord(m);
|
||||
}
|
||||
|
||||
// Set the pragma callback so we can detect
|
||||
builder.SetPragmaCallback(&ScriptMachine::pragmaCallback, this);
|
||||
|
@ -315,11 +310,11 @@ bool ScriptMachine::executeScript(const QString &script, bool isInDebug) {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (isInDebug) {
|
||||
// Let the debugger hold an engine pointer that can be used by the
|
||||
// callbacks
|
||||
_debugger->setEngine(_engine);
|
||||
// Let the debugger hold an engine pointer that can be used by the
|
||||
// callbacks
|
||||
_debugger->setEngine(_engine);
|
||||
|
||||
if (isInDebug) {
|
||||
// Allow the user to initialize the debugging before moving on
|
||||
MessageInfo info;
|
||||
info.message = tr("Debugging, waiting for commands.");
|
||||
|
@ -382,6 +377,10 @@ bool ScriptMachine::executeScript(const QString &script, bool isInDebug) {
|
|||
r = 0;
|
||||
}
|
||||
|
||||
MessageInfo info;
|
||||
info.message = tr("The script exited with ") + QString::number(r);
|
||||
emit onOutput(MessageType::Info, info);
|
||||
|
||||
// Return the context after retrieving the return value
|
||||
_ctxMgr->DoneWithContext(ctx);
|
||||
|
||||
|
@ -569,7 +568,7 @@ int ScriptMachine::includeCallback(const QString &include, bool quotedInclude,
|
|||
if (isAbsolute) {
|
||||
inc = include;
|
||||
} else {
|
||||
auto pwd = QDir(QFileInfo(from).filePath());
|
||||
auto pwd = QFileInfo(from).absoluteDir();
|
||||
inc = pwd.absoluteFilePath(include);
|
||||
}
|
||||
} else {
|
||||
|
@ -1612,6 +1611,7 @@ void ScriptMachine::registerEngineAddon(asIScriptEngine *engine) {
|
|||
RegisterScriptHandle(engine);
|
||||
RegisterColor(engine);
|
||||
RegisterQJson(engine);
|
||||
RegisterScriptFile(engine);
|
||||
registerExceptionRoutines(engine);
|
||||
registerEngineAssert(engine);
|
||||
}
|
||||
|
|
|
@ -135,10 +135,8 @@ private:
|
|||
|
||||
bool isType(asITypeInfo *tinfo, RegisteredType type);
|
||||
|
||||
static int execSystemCmd(const std::string &exe, const std::string ¶ms,
|
||||
std::string &out);
|
||||
|
||||
static int execSystemCmd(const std::string &exe, const std::string ¶ms);
|
||||
static int execSystemCmd(QString &out, const QString &exe,
|
||||
const QString ¶ms, int timeout);
|
||||
|
||||
private:
|
||||
static void messageCallback(const asSMessageInfo *msg, void *param);
|
||||
|
|
|
@ -109,10 +109,6 @@ void SettingManager::load() {
|
|||
Q_ASSERT(defaultFontSize > 0);
|
||||
HANDLE_CONFIG;
|
||||
|
||||
if (!CONFIG.isWritable()) {
|
||||
Logger::warning(tr("ConfigUnableSave"));
|
||||
}
|
||||
|
||||
READ_CONFIG_INT(m_themeID, SKIN_THEME, 0);
|
||||
m_themeID = qBound(0, m_themeID,
|
||||
QMetaEnum::fromType<SkinManager::Theme>().keyCount());
|
||||
|
@ -214,6 +210,13 @@ void SettingManager::setLogCount(qsizetype newLogCount) {
|
|||
m_logCount = newLogCount;
|
||||
}
|
||||
|
||||
void SettingManager::checkWriteableAndWarn() {
|
||||
HANDLE_CONFIG;
|
||||
if (!CONFIG.isWritable()) {
|
||||
Logger::warning(tr("ConfigUnableSave"));
|
||||
}
|
||||
}
|
||||
|
||||
bool SettingManager::checkUpdate() const { return m_checkUpdate; }
|
||||
|
||||
void SettingManager::setCheckUpdate(bool newCheckUpdate) {
|
||||
|
|
|
@ -173,6 +173,9 @@ public:
|
|||
qsizetype logCount() const;
|
||||
void setLogCount(qsizetype newLogCount);
|
||||
|
||||
public:
|
||||
void checkWriteableAndWarn();
|
||||
|
||||
signals:
|
||||
void sigEditorfontSizeChanged(int v);
|
||||
void sigDecodeStrlimitChanged(int v);
|
||||
|
|
|
@ -86,6 +86,10 @@ QString WingAngelAPI::retranslate(const QString &str) {
|
|||
return QApplication::tr(str.toLatin1());
|
||||
}
|
||||
|
||||
QStringList WingAngelAPI::registerScriptMarcos() const {
|
||||
return {"EXEC_BASE", "AS_ARRAY_EXT", "AS_DICTIONARY_EXT"};
|
||||
}
|
||||
|
||||
WingHex::IWingPlugin::RegisteredEvents WingAngelAPI::registeredEvents() const {
|
||||
RegisteredEvents evs;
|
||||
evs.setFlag(RegisteredEvent::PluginFileOpened);
|
||||
|
|
|
@ -49,6 +49,8 @@ public:
|
|||
|
||||
virtual QString retranslate(const QString &str) override;
|
||||
|
||||
virtual QStringList registerScriptMarcos() const override;
|
||||
|
||||
private:
|
||||
virtual void eventPluginFile(PluginFileEvent e, FileType type,
|
||||
const QString &newfileName, int handle,
|
||||
|
@ -167,6 +169,7 @@ private:
|
|||
static double QModelIndex_dataDouble(const QModelIndex &idx);
|
||||
|
||||
private:
|
||||
// for EXEC_BASE marco
|
||||
WING_SERVICE bool execScriptCode(const WingHex::SenderInfo &sender,
|
||||
const QString &code);
|
||||
WING_SERVICE bool execScript(const WingHex::SenderInfo &sender,
|
||||
|
|
|
@ -13,5 +13,4 @@ The following components are all third-party components used by the software. Th
|
|||
* [QConsoleWidget](https://github.com/gapost/qconsolewidget) (MIT, **FORK** -> AGPL-3.0)
|
||||
* [QColorPicker](https://github.com/arsdever/qcolorpicker) (MIT)
|
||||
* [QtJsonModel](https://github.com/dridk/QJsonmodel) (MIT)
|
||||
* [nlohmann/json](https://github.com/nlohmann/json) (MIT)
|
||||
* [Qt](https://www.qt.io/) (LGPL)
|
||||
|
|
|
@ -446,32 +446,29 @@ ErrFile EditorView::save(const QString &workSpaceName, const QString &path,
|
|||
bool needAdjustFile = !QFile::exists(fileName);
|
||||
bool needAdjustWs = false;
|
||||
|
||||
ScopeGuard guard(
|
||||
[] {},
|
||||
[&] {
|
||||
if (Utilities::isRoot()) {
|
||||
// a trick off when root under linux OS
|
||||
// When new file created, change file's permission to 666.
|
||||
auto adjustPermission = [&]() {
|
||||
if (Utilities::isRoot()) {
|
||||
// a trick off when root under linux OS
|
||||
// When new file created, change file's permission to 666.
|
||||
|
||||
// Because you cannot open it when you use it in common user
|
||||
// after saving under root user.
|
||||
// Because you cannot open it when you use it in common user
|
||||
// after saving under root user.
|
||||
|
||||
// It's a workaround and not eligent for permission system
|
||||
// It's a workaround and not eligent for permission system
|
||||
|
||||
if (needAdjustFile) {
|
||||
if (Utilities::isFileOwnerRoot(fileName)) {
|
||||
Utilities::fixUpFilePermissions(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
if (needAdjustWs) {
|
||||
if (Utilities::isFileOwnerRoot(workSpaceName)) {
|
||||
Utilities::fixUpFilePermissions(workSpaceName);
|
||||
}
|
||||
if (needAdjustFile) {
|
||||
if (Utilities::isFileOwnerRoot(fileName)) {
|
||||
Utilities::fixUpFilePermissions(fileName);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (needAdjustWs) {
|
||||
if (Utilities::isFileOwnerRoot(workSpaceName)) {
|
||||
Utilities::fixUpFilePermissions(workSpaceName);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
if (isNewFile()) {
|
||||
|
@ -535,7 +532,9 @@ ErrFile EditorView::save(const QString &workSpaceName, const QString &path,
|
|||
m_docType = DocumentType::File;
|
||||
doc->setDocSaved();
|
||||
}
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
adjustPermission();
|
||||
#endif
|
||||
return ErrFile::Success;
|
||||
}
|
||||
}
|
||||
|
@ -545,7 +544,9 @@ ErrFile EditorView::save(const QString &workSpaceName, const QString &path,
|
|||
doc->setDocSaved();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
adjustPermission();
|
||||
#endif
|
||||
return ErrFile::Success;
|
||||
}
|
||||
|
||||
|
|
|
@ -209,6 +209,9 @@ MainWindow::MainWindow(SplashDialog *splash) : FramelessMainWindow() {
|
|||
log.setLogLevel(Logger::Level(set.logLevel()));
|
||||
connect(&log, &Logger::log, m_logbrowser, &QTextBrowser::append);
|
||||
|
||||
// check config writable
|
||||
set.checkWriteableAndWarn();
|
||||
|
||||
// launch plugin system
|
||||
if (splash)
|
||||
splash->setInfoText(tr("SetupPluginSystem"));
|
||||
|
|
|
@ -550,6 +550,9 @@ public:
|
|||
return {};
|
||||
}
|
||||
|
||||
// Note: must be valid identifier
|
||||
virtual QStringList registerScriptMarcos() const { return {}; }
|
||||
|
||||
public:
|
||||
virtual void eventSelectionChanged(const QByteArrayList &selections,
|
||||
bool isPreview) {
|
||||
|
|
|
@ -58,6 +58,8 @@ void PluginSystem::initCheckingEngine() {
|
|||
|
||||
void PluginSystem::finalizeCheckingEngine() { _engine->ShutDownAndRelease(); }
|
||||
|
||||
QStringList PluginSystem::scriptMarcos() const { return _scriptMarcos; }
|
||||
|
||||
const QList<IWingPlugin *> &PluginSystem::plugins() const {
|
||||
return _loadedplgs;
|
||||
}
|
||||
|
@ -234,17 +236,11 @@ PluginSystem::PluginStatus
|
|||
PluginSystem::checkPluginMetadata(const PluginInfo &meta, bool isPlg) {
|
||||
constexpr auto puid_limit = 36; // same as uuid length, so enough
|
||||
|
||||
if (meta.id.isEmpty() && meta.id.length() > puid_limit) {
|
||||
if (meta.id.length() > puid_limit) {
|
||||
return PluginStatus::InvalidID;
|
||||
}
|
||||
|
||||
if (meta.id.front().isDigit()) {
|
||||
return PluginStatus::InvalidID;
|
||||
}
|
||||
auto r = std::find_if(meta.id.begin(), meta.id.end(), [](const QChar &ch) {
|
||||
return !ch.isLetterOrNumber() && ch != '_';
|
||||
});
|
||||
if (r != meta.id.end()) {
|
||||
if (!isValidIdentifier(meta.id)) {
|
||||
return PluginStatus::InvalidID;
|
||||
}
|
||||
|
||||
|
@ -264,6 +260,23 @@ PluginSystem::checkPluginMetadata(const PluginInfo &meta, bool isPlg) {
|
|||
return PluginStatus::Valid;
|
||||
}
|
||||
|
||||
bool PluginSystem::isValidIdentifier(const QString &str) {
|
||||
if (str.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
auto pch = str.cbegin();
|
||||
if (pch->isDigit()) {
|
||||
return false;
|
||||
}
|
||||
pch++;
|
||||
for (; pch != str.cend(); pch++) {
|
||||
if (!pch->isLetterOrNumber() && *pch != '_') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PluginSystem::checkPluginCanOpenedFile(IWingPlugin *plg) {
|
||||
if (plg == nullptr) {
|
||||
return false;
|
||||
|
@ -836,6 +849,27 @@ void PluginSystem::registerEnums(IWingPlugin *plg) {
|
|||
_angelplg->registerScriptEnums(id, passedEnums);
|
||||
}
|
||||
|
||||
void PluginSystem::registerMarcos(IWingPlugin *plg) {
|
||||
Q_ASSERT(plg);
|
||||
|
||||
auto id = getPUID(plg).toUpper();
|
||||
auto sep = QStringLiteral("_");
|
||||
_scriptMarcos.append(sep + id + sep);
|
||||
|
||||
QStringList invalidMarco;
|
||||
for (auto &m : plg->registerScriptMarcos()) {
|
||||
if (isValidIdentifier(m)) {
|
||||
_scriptMarcos.append(sep + id + sep + m + sep);
|
||||
} else {
|
||||
invalidMarco.append(m);
|
||||
}
|
||||
}
|
||||
|
||||
if (!invalidMarco.isEmpty()) {
|
||||
Logger::warning(tr("InvalidMarcosRegister:") + invalidMarco.join(", "));
|
||||
}
|
||||
}
|
||||
|
||||
void PluginSystem::registerEvents(IWingPlugin *plg) {
|
||||
Q_ASSERT(plg);
|
||||
auto evs = plg->registeredEvents();
|
||||
|
@ -1193,6 +1227,7 @@ void PluginSystem::loadPlugin(IWingPlugin *p, PluginInfo &meta,
|
|||
|
||||
registerFns(p);
|
||||
registerEnums(p);
|
||||
registerMarcos(p);
|
||||
registerEvents(p);
|
||||
connectInterface(p);
|
||||
|
||||
|
|
|
@ -160,6 +160,8 @@ public:
|
|||
|
||||
IWingDevice *ext2Device(const QString &ext);
|
||||
|
||||
QStringList scriptMarcos() const;
|
||||
|
||||
public:
|
||||
PluginInfo getPluginInfo(IWingPluginBase *plg) const;
|
||||
|
||||
|
@ -205,12 +207,15 @@ private:
|
|||
|
||||
PluginStatus checkPluginMetadata(const PluginInfo &meta, bool isPlg);
|
||||
|
||||
static bool isValidIdentifier(const QString &str);
|
||||
|
||||
void retranslateMetadata(IWingPluginBase *plg, PluginInfo &meta);
|
||||
|
||||
private:
|
||||
void registerFns(IWingPlugin *plg);
|
||||
void registerUnSafeFns(IWingPlugin *plg);
|
||||
void registerEnums(IWingPlugin *plg);
|
||||
void registerMarcos(IWingPlugin *plg);
|
||||
void registerEvents(IWingPlugin *plg);
|
||||
|
||||
static QString getScriptFnSig(const QString &fnName,
|
||||
|
@ -390,6 +395,8 @@ private:
|
|||
WingAngelAPI *_angelplg = nullptr;
|
||||
asCScriptEngine *_engine = nullptr;
|
||||
|
||||
QStringList _scriptMarcos;
|
||||
|
||||
QReadWriteLock _rwlock;
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,514 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#include "scriptfile.h"
|
||||
|
||||
BEGIN_AS_NAMESPACE
|
||||
|
||||
CScriptFile *ScriptFile_Factory() { return new CScriptFile(); }
|
||||
|
||||
void ScriptFile_Factory_Generic(asIScriptGeneric *gen) {
|
||||
*(CScriptFile **)gen->GetAddressOfReturnLocation() = ScriptFile_Factory();
|
||||
}
|
||||
|
||||
void ScriptFile_AddRef_Generic(asIScriptGeneric *gen) {
|
||||
CScriptFile *file = (CScriptFile *)gen->GetObject();
|
||||
file->AddRef();
|
||||
}
|
||||
|
||||
void ScriptFile_Release_Generic(asIScriptGeneric *gen) {
|
||||
CScriptFile *file = (CScriptFile *)gen->GetObject();
|
||||
file->Release();
|
||||
}
|
||||
|
||||
void ScriptFile_Open_Generic(asIScriptGeneric *gen) {
|
||||
CScriptFile *file = (CScriptFile *)gen->GetObject();
|
||||
QString *f = (QString *)gen->GetArgAddress(0);
|
||||
auto r = file->Open(*f);
|
||||
gen->SetReturnByte(r);
|
||||
}
|
||||
|
||||
void ScriptFile_Close_Generic(asIScriptGeneric *gen) {
|
||||
CScriptFile *file = (CScriptFile *)gen->GetObject();
|
||||
auto r = file->Close();
|
||||
gen->SetReturnByte(r);
|
||||
}
|
||||
|
||||
void ScriptFile_GetSize_Generic(asIScriptGeneric *gen) {
|
||||
CScriptFile *file = (CScriptFile *)gen->GetObject();
|
||||
qint64 r = file->GetSize();
|
||||
gen->SetReturnQWord(r);
|
||||
}
|
||||
|
||||
void ScriptFile_ReadString_Generic(asIScriptGeneric *gen) {
|
||||
CScriptFile *file = (CScriptFile *)gen->GetObject();
|
||||
int len = gen->GetArgDWord(0);
|
||||
auto str = file->ReadString(len);
|
||||
gen->SetReturnObject(&str);
|
||||
}
|
||||
|
||||
void ScriptFile_ReadLine_Generic(asIScriptGeneric *gen) {
|
||||
CScriptFile *file = (CScriptFile *)gen->GetObject();
|
||||
auto str = file->ReadLine();
|
||||
gen->SetReturnObject(&str);
|
||||
}
|
||||
|
||||
void ScriptFile_ReadInt_Generic(asIScriptGeneric *gen) {
|
||||
CScriptFile *file = (CScriptFile *)gen->GetObject();
|
||||
asUINT bytes = *(asUINT *)gen->GetAddressOfArg(0);
|
||||
*(asINT64 *)gen->GetAddressOfReturnLocation() = file->ReadInt(bytes);
|
||||
}
|
||||
|
||||
void ScriptFile_ReadUInt_Generic(asIScriptGeneric *gen) {
|
||||
CScriptFile *file = (CScriptFile *)gen->GetObject();
|
||||
asUINT bytes = *(asUINT *)gen->GetAddressOfArg(0);
|
||||
*(asQWORD *)gen->GetAddressOfReturnLocation() = file->ReadUInt(bytes);
|
||||
}
|
||||
|
||||
void ScriptFile_ReadFloat_Generic(asIScriptGeneric *gen) {
|
||||
CScriptFile *file = (CScriptFile *)gen->GetObject();
|
||||
*(float *)gen->GetAddressOfReturnLocation() = file->ReadFloat();
|
||||
}
|
||||
|
||||
void ScriptFile_ReadDouble_Generic(asIScriptGeneric *gen) {
|
||||
CScriptFile *file = (CScriptFile *)gen->GetObject();
|
||||
*(double *)gen->GetAddressOfReturnLocation() = file->ReadDouble();
|
||||
}
|
||||
|
||||
void ScriptFile_IsEOF_Generic(asIScriptGeneric *gen) {
|
||||
CScriptFile *file = (CScriptFile *)gen->GetObject();
|
||||
bool r = file->IsEOF();
|
||||
gen->SetReturnByte(r);
|
||||
}
|
||||
|
||||
void ScriptFile_GetPos_Generic(asIScriptGeneric *gen) {
|
||||
CScriptFile *file = (CScriptFile *)gen->GetObject();
|
||||
gen->SetReturnDWord(file->GetPos());
|
||||
}
|
||||
|
||||
void ScriptFile_SetPos_Generic(asIScriptGeneric *gen) {
|
||||
CScriptFile *file = (CScriptFile *)gen->GetObject();
|
||||
auto pos = qint64(gen->GetArgQWord(0));
|
||||
gen->SetReturnByte(file->SetPos(pos));
|
||||
}
|
||||
|
||||
void ScriptFile_MovePos_Generic(asIScriptGeneric *gen) {
|
||||
CScriptFile *file = (CScriptFile *)gen->GetObject();
|
||||
auto delta = qint64(gen->GetArgQWord(0));
|
||||
gen->SetReturnByte(file->MovePos(delta));
|
||||
}
|
||||
|
||||
void RegisterScriptFile_Native(asIScriptEngine *engine) {
|
||||
int r;
|
||||
|
||||
r = engine->RegisterObjectType("file", 0, asOBJ_REF);
|
||||
Q_ASSERT(r >= 0);
|
||||
Q_UNUSED(r);
|
||||
r = engine->RegisterObjectBehaviour("file", asBEHAVE_FACTORY, "file @f()",
|
||||
asFUNCTION(ScriptFile_Factory),
|
||||
asCALL_CDECL);
|
||||
Q_ASSERT(r >= 0);
|
||||
Q_UNUSED(r);
|
||||
r = engine->RegisterObjectBehaviour("file", asBEHAVE_ADDREF, "void f()",
|
||||
asMETHOD(CScriptFile, AddRef),
|
||||
asCALL_THISCALL);
|
||||
Q_ASSERT(r >= 0);
|
||||
Q_UNUSED(r);
|
||||
r = engine->RegisterObjectBehaviour("file", asBEHAVE_RELEASE, "void f()",
|
||||
asMETHOD(CScriptFile, Release),
|
||||
asCALL_THISCALL);
|
||||
Q_ASSERT(r >= 0);
|
||||
Q_UNUSED(r);
|
||||
|
||||
r = engine->RegisterObjectMethod("file", "bool open(const string &in)",
|
||||
asMETHOD(CScriptFile, Open),
|
||||
asCALL_THISCALL);
|
||||
Q_ASSERT(r >= 0);
|
||||
Q_UNUSED(r);
|
||||
r = engine->RegisterObjectMethod(
|
||||
"file", "bool close()", asMETHOD(CScriptFile, Close), asCALL_THISCALL);
|
||||
Q_ASSERT(r >= 0);
|
||||
Q_UNUSED(r);
|
||||
r = engine->RegisterObjectMethod("file", "int64 getSize() const",
|
||||
asMETHOD(CScriptFile, GetSize),
|
||||
asCALL_THISCALL);
|
||||
Q_ASSERT(r >= 0);
|
||||
Q_UNUSED(r);
|
||||
r = engine->RegisterObjectMethod("file", "bool isEndOfFile() const",
|
||||
asMETHOD(CScriptFile, IsEOF),
|
||||
asCALL_THISCALL);
|
||||
Q_ASSERT(r >= 0);
|
||||
Q_UNUSED(r);
|
||||
r = engine->RegisterObjectMethod("file", "string readString(uint)",
|
||||
asMETHOD(CScriptFile, ReadString),
|
||||
asCALL_THISCALL);
|
||||
Q_ASSERT(r >= 0);
|
||||
Q_UNUSED(r);
|
||||
r = engine->RegisterObjectMethod("file", "string readLine()",
|
||||
asMETHOD(CScriptFile, ReadLine),
|
||||
asCALL_THISCALL);
|
||||
Q_ASSERT(r >= 0);
|
||||
Q_UNUSED(r);
|
||||
r = engine->RegisterObjectMethod("file", "int64 readInt(uint)",
|
||||
asMETHOD(CScriptFile, ReadInt),
|
||||
asCALL_THISCALL);
|
||||
Q_ASSERT(r >= 0);
|
||||
Q_UNUSED(r);
|
||||
r = engine->RegisterObjectMethod("file", "uint64 readUInt(uint)",
|
||||
asMETHOD(CScriptFile, ReadUInt),
|
||||
asCALL_THISCALL);
|
||||
Q_ASSERT(r >= 0);
|
||||
Q_UNUSED(r);
|
||||
r = engine->RegisterObjectMethod("file", "float readFloat()",
|
||||
asMETHOD(CScriptFile, ReadFloat),
|
||||
asCALL_THISCALL);
|
||||
Q_ASSERT(r >= 0);
|
||||
Q_UNUSED(r);
|
||||
r = engine->RegisterObjectMethod("file", "double readDouble()",
|
||||
asMETHOD(CScriptFile, ReadDouble),
|
||||
asCALL_THISCALL);
|
||||
Q_ASSERT(r >= 0);
|
||||
Q_UNUSED(r);
|
||||
|
||||
r = engine->RegisterObjectMethod("file", "int getPos() const",
|
||||
asMETHOD(CScriptFile, GetPos),
|
||||
asCALL_THISCALL);
|
||||
Q_ASSERT(r >= 0);
|
||||
Q_UNUSED(r);
|
||||
r = engine->RegisterObjectMethod("file", "bool setPos(int64)",
|
||||
asMETHOD(CScriptFile, SetPos),
|
||||
asCALL_THISCALL);
|
||||
Q_ASSERT(r >= 0);
|
||||
Q_UNUSED(r);
|
||||
r = engine->RegisterObjectMethod("file", "bool movePos(int64)",
|
||||
asMETHOD(CScriptFile, MovePos),
|
||||
asCALL_THISCALL);
|
||||
Q_ASSERT(r >= 0);
|
||||
Q_UNUSED(r);
|
||||
|
||||
r = engine->RegisterObjectProperty(
|
||||
"file", "bool mostSignificantByteFirst",
|
||||
asOFFSET(CScriptFile, mostSignificantByteFirst));
|
||||
Q_ASSERT(r >= 0);
|
||||
Q_UNUSED(r);
|
||||
}
|
||||
|
||||
void RegisterScriptFile_Generic(asIScriptEngine *engine) {
|
||||
int r;
|
||||
|
||||
r = engine->RegisterObjectType("file", 0, asOBJ_REF);
|
||||
Q_ASSERT(r >= 0);
|
||||
Q_UNUSED(r);
|
||||
r = engine->RegisterObjectBehaviour("file", asBEHAVE_FACTORY, "file @f()",
|
||||
asFUNCTION(ScriptFile_Factory_Generic),
|
||||
asCALL_GENERIC);
|
||||
Q_ASSERT(r >= 0);
|
||||
Q_UNUSED(r);
|
||||
r = engine->RegisterObjectBehaviour("file", asBEHAVE_ADDREF, "void f()",
|
||||
asFUNCTION(ScriptFile_AddRef_Generic),
|
||||
asCALL_GENERIC);
|
||||
Q_ASSERT(r >= 0);
|
||||
Q_UNUSED(r);
|
||||
r = engine->RegisterObjectBehaviour("file", asBEHAVE_RELEASE, "void f()",
|
||||
asFUNCTION(ScriptFile_Release_Generic),
|
||||
asCALL_GENERIC);
|
||||
Q_ASSERT(r >= 0);
|
||||
Q_UNUSED(r);
|
||||
|
||||
r = engine->RegisterObjectMethod("file", "bool open(const string &in)",
|
||||
asFUNCTION(ScriptFile_Open_Generic),
|
||||
asCALL_GENERIC);
|
||||
Q_ASSERT(r >= 0);
|
||||
Q_UNUSED(r);
|
||||
r = engine->RegisterObjectMethod("file", "bool close()",
|
||||
asFUNCTION(ScriptFile_Close_Generic),
|
||||
asCALL_GENERIC);
|
||||
Q_ASSERT(r >= 0);
|
||||
Q_UNUSED(r);
|
||||
r = engine->RegisterObjectMethod("file", "int64 getSize() const",
|
||||
asFUNCTION(ScriptFile_GetSize_Generic),
|
||||
asCALL_GENERIC);
|
||||
Q_ASSERT(r >= 0);
|
||||
Q_UNUSED(r);
|
||||
r = engine->RegisterObjectMethod("file", "bool isEndOfFile() const",
|
||||
asFUNCTION(ScriptFile_IsEOF_Generic),
|
||||
asCALL_GENERIC);
|
||||
Q_ASSERT(r >= 0);
|
||||
Q_UNUSED(r);
|
||||
r = engine->RegisterObjectMethod("file", "string readString(uint)",
|
||||
asFUNCTION(ScriptFile_ReadString_Generic),
|
||||
asCALL_GENERIC);
|
||||
Q_ASSERT(r >= 0);
|
||||
Q_UNUSED(r);
|
||||
r = engine->RegisterObjectMethod("file", "string readLine()",
|
||||
asFUNCTION(ScriptFile_ReadLine_Generic),
|
||||
asCALL_GENERIC);
|
||||
Q_ASSERT(r >= 0);
|
||||
Q_UNUSED(r);
|
||||
r = engine->RegisterObjectMethod("file", "int64 readInt(uint)",
|
||||
asFUNCTION(ScriptFile_ReadInt_Generic),
|
||||
asCALL_GENERIC);
|
||||
Q_ASSERT(r >= 0);
|
||||
Q_UNUSED(r);
|
||||
r = engine->RegisterObjectMethod("file", "uint64 readUInt(uint)",
|
||||
asFUNCTION(ScriptFile_ReadUInt_Generic),
|
||||
asCALL_GENERIC);
|
||||
Q_ASSERT(r >= 0);
|
||||
Q_UNUSED(r);
|
||||
r = engine->RegisterObjectMethod("file", "float readFloat()",
|
||||
asFUNCTION(ScriptFile_ReadFloat_Generic),
|
||||
asCALL_GENERIC);
|
||||
Q_ASSERT(r >= 0);
|
||||
Q_UNUSED(r);
|
||||
r = engine->RegisterObjectMethod("file", "double readDouble()",
|
||||
asFUNCTION(ScriptFile_ReadDouble_Generic),
|
||||
asCALL_GENERIC);
|
||||
Q_ASSERT(r >= 0);
|
||||
Q_UNUSED(r);
|
||||
|
||||
r = engine->RegisterObjectMethod("file", "int getPos() const",
|
||||
asFUNCTION(ScriptFile_GetPos_Generic),
|
||||
asCALL_GENERIC);
|
||||
Q_ASSERT(r >= 0);
|
||||
Q_UNUSED(r);
|
||||
r = engine->RegisterObjectMethod("file", "bool setPos(int64)",
|
||||
asFUNCTION(ScriptFile_SetPos_Generic),
|
||||
asCALL_GENERIC);
|
||||
Q_ASSERT(r >= 0);
|
||||
Q_UNUSED(r);
|
||||
r = engine->RegisterObjectMethod("file", "bool movePos(int64)",
|
||||
asFUNCTION(ScriptFile_MovePos_Generic),
|
||||
asCALL_GENERIC);
|
||||
Q_ASSERT(r >= 0);
|
||||
Q_UNUSED(r);
|
||||
|
||||
r = engine->RegisterObjectProperty(
|
||||
"file", "bool mostSignificantByteFirst",
|
||||
asOFFSET(CScriptFile, mostSignificantByteFirst));
|
||||
Q_ASSERT(r >= 0);
|
||||
Q_UNUSED(r);
|
||||
}
|
||||
|
||||
void RegisterScriptFile(asIScriptEngine *engine) {
|
||||
if (strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY"))
|
||||
RegisterScriptFile_Generic(engine);
|
||||
else
|
||||
RegisterScriptFile_Native(engine);
|
||||
}
|
||||
|
||||
CScriptFile::CScriptFile() {
|
||||
refCount = 1;
|
||||
mostSignificantByteFirst = false;
|
||||
}
|
||||
|
||||
CScriptFile::~CScriptFile() { Close(); }
|
||||
|
||||
void CScriptFile::AddRef() const { asAtomicInc(refCount); }
|
||||
|
||||
void CScriptFile::Release() const {
|
||||
if (asAtomicDec(refCount) == 0)
|
||||
delete this;
|
||||
}
|
||||
|
||||
bool CScriptFile::Open(const QString &filename) {
|
||||
// Close the previously opened file handle
|
||||
if (file.isOpen())
|
||||
Close();
|
||||
|
||||
file.setFileName(filename);
|
||||
return file.open(QFile::ReadOnly);
|
||||
}
|
||||
|
||||
bool CScriptFile::Close() {
|
||||
if (!file.isOpen())
|
||||
return false;
|
||||
|
||||
file.close();
|
||||
file.setFileName({});
|
||||
return true;
|
||||
}
|
||||
|
||||
asINT64 CScriptFile::GetSize() const {
|
||||
if (!file.isOpen())
|
||||
return -1;
|
||||
|
||||
return file.size();
|
||||
}
|
||||
|
||||
int CScriptFile::GetPos() const {
|
||||
if (!file.isOpen())
|
||||
return -1;
|
||||
|
||||
return file.pos();
|
||||
}
|
||||
|
||||
bool CScriptFile::SetPos(asINT64 pos) {
|
||||
if (!file.isOpen())
|
||||
return false;
|
||||
|
||||
return file.seek(pos);
|
||||
}
|
||||
|
||||
bool CScriptFile::MovePos(asINT64 delta) {
|
||||
if (!file.isOpen())
|
||||
return false;
|
||||
|
||||
return file.seek(file.pos() + delta);
|
||||
}
|
||||
|
||||
QString CScriptFile::ReadString(unsigned int length) {
|
||||
if (!file.isOpen())
|
||||
return {};
|
||||
|
||||
return QString::fromUtf8(file.read(length));
|
||||
}
|
||||
|
||||
QString CScriptFile::ReadLine() {
|
||||
if (!file.isOpen())
|
||||
return {};
|
||||
|
||||
return QString::fromUtf8(file.readLine());
|
||||
}
|
||||
|
||||
asINT64 CScriptFile::ReadInt(asUINT bytes) {
|
||||
if (!file.isOpen())
|
||||
return 0;
|
||||
|
||||
if (bytes > 8)
|
||||
bytes = 8;
|
||||
if (bytes == 0)
|
||||
return 0;
|
||||
|
||||
char buf[8];
|
||||
size_t r = file.read(buf, 8);
|
||||
if (r == 0)
|
||||
return 0;
|
||||
|
||||
asINT64 val = 0;
|
||||
if (mostSignificantByteFirst) {
|
||||
unsigned int n = 0;
|
||||
for (; n < bytes; n++)
|
||||
val |= asQWORD(buf[n]) << ((bytes - n - 1) * 8);
|
||||
|
||||
// Check the most significant byte to determine if the rest
|
||||
// of the qword must be filled to give a negative value
|
||||
if (buf[0] & 0x80)
|
||||
for (; n < 8; n++)
|
||||
val |= asQWORD(0xFF) << (n * 8);
|
||||
} else {
|
||||
unsigned int n = 0;
|
||||
for (; n < bytes; n++)
|
||||
val |= asQWORD(buf[n]) << (n * 8);
|
||||
|
||||
// Check the most significant byte to determine if the rest
|
||||
// of the qword must be filled to give a negative value
|
||||
if (buf[bytes - 1] & 0x80)
|
||||
for (; n < 8; n++)
|
||||
val |= asQWORD(0xFF) << (n * 8);
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
asQWORD CScriptFile::ReadUInt(asUINT bytes) {
|
||||
if (!file.isOpen())
|
||||
return 0;
|
||||
|
||||
if (bytes > 8)
|
||||
bytes = 8;
|
||||
if (bytes == 0)
|
||||
return 0;
|
||||
|
||||
char buf[8];
|
||||
size_t r = file.read(buf, 8);
|
||||
if (r == 0)
|
||||
return 0;
|
||||
|
||||
asQWORD val = 0;
|
||||
if (mostSignificantByteFirst) {
|
||||
unsigned int n = 0;
|
||||
for (; n < bytes; n++)
|
||||
val |= asQWORD(buf[n]) << ((bytes - n - 1) * 8);
|
||||
} else {
|
||||
unsigned int n = 0;
|
||||
for (; n < bytes; n++)
|
||||
val |= asQWORD(buf[n]) << (n * 8);
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
float CScriptFile::ReadFloat() {
|
||||
if (!file.isOpen())
|
||||
return 0;
|
||||
|
||||
char buf[4];
|
||||
size_t r = file.read(buf, 4);
|
||||
if (r == 0)
|
||||
return 0;
|
||||
|
||||
union conv {
|
||||
asUINT val;
|
||||
float fp;
|
||||
} value = {0};
|
||||
if (mostSignificantByteFirst) {
|
||||
unsigned int n = 0;
|
||||
for (; n < 4; n++)
|
||||
value.val |= asUINT(buf[n]) << ((3 - n) * 8);
|
||||
} else {
|
||||
unsigned int n = 0;
|
||||
for (; n < 4; n++)
|
||||
value.val |= asUINT(buf[n]) << (n * 8);
|
||||
}
|
||||
|
||||
return value.fp;
|
||||
}
|
||||
|
||||
double CScriptFile::ReadDouble() {
|
||||
if (!file.isOpen())
|
||||
return 0;
|
||||
|
||||
char buf[8];
|
||||
size_t r = file.read(buf, 8);
|
||||
if (r == 0)
|
||||
return 0;
|
||||
|
||||
union conv {
|
||||
asQWORD val;
|
||||
double fp;
|
||||
} value = {0};
|
||||
if (mostSignificantByteFirst) {
|
||||
unsigned int n = 0;
|
||||
for (; n < 8; n++)
|
||||
value.val |= asQWORD(buf[n]) << ((7 - n) * 8);
|
||||
} else {
|
||||
unsigned int n = 0;
|
||||
for (; n < 8; n++)
|
||||
value.val |= asQWORD(buf[n]) << (n * 8);
|
||||
}
|
||||
|
||||
return value.fp;
|
||||
}
|
||||
|
||||
bool CScriptFile::IsEOF() const {
|
||||
if (!file.isOpen())
|
||||
return true;
|
||||
|
||||
return file.atEnd();
|
||||
}
|
||||
|
||||
END_AS_NAMESPACE
|
|
@ -0,0 +1,84 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#ifndef SCRIPTFILE_H
|
||||
#define SCRIPTFILE_H
|
||||
|
||||
//---------------------------
|
||||
// Declaration
|
||||
//
|
||||
|
||||
#ifndef ANGELSCRIPT_H
|
||||
// Avoid having to inform include path if header is already include before
|
||||
#include <angelscript.h>
|
||||
#endif
|
||||
|
||||
#include <QFile>
|
||||
#include <QString>
|
||||
|
||||
BEGIN_AS_NAMESPACE
|
||||
|
||||
class CScriptFile {
|
||||
public:
|
||||
CScriptFile();
|
||||
|
||||
void AddRef() const;
|
||||
void Release() const;
|
||||
|
||||
bool Open(const QString &filename);
|
||||
bool Close();
|
||||
asINT64 GetSize() const;
|
||||
bool IsEOF() const;
|
||||
|
||||
// Reading
|
||||
QString ReadString(unsigned int length);
|
||||
QString ReadLine();
|
||||
asINT64 ReadInt(asUINT bytes);
|
||||
asQWORD ReadUInt(asUINT bytes);
|
||||
float ReadFloat();
|
||||
double ReadDouble();
|
||||
|
||||
// Cursor
|
||||
int GetPos() const;
|
||||
bool SetPos(asINT64 pos);
|
||||
bool MovePos(asINT64 delta);
|
||||
|
||||
// Big-endian = most significant byte first
|
||||
bool mostSignificantByteFirst;
|
||||
|
||||
protected:
|
||||
~CScriptFile();
|
||||
|
||||
mutable int refCount;
|
||||
QFile file;
|
||||
};
|
||||
|
||||
// This function will determine the configuration of the engine
|
||||
// and use one of the two functions below to register the file type
|
||||
void RegisterScriptFile(asIScriptEngine *engine);
|
||||
|
||||
// Call this function to register the file type
|
||||
// using native calling conventions
|
||||
void RegisterScriptFile_Native(asIScriptEngine *engine);
|
||||
|
||||
// Use this one instead if native calling conventions
|
||||
// are not supported on the target platform
|
||||
void RegisterScriptFile_Generic(asIScriptEngine *engine);
|
||||
|
||||
END_AS_NAMESPACE
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue