source: XmlTools2/trunk/xmlcustomcode.cpp @ 967

Last change on this file since 967 was 967, checked in by s10k, 8 years ago

XmlTools
Some more little optimizations and updated readme

File size: 5.3 KB
Line 
1#include "xmlcustomcode.h"
2
3// http://stackoverflow.com/questions/7092765/what-does-it-mean-to-have-an-undefined-reference-to-a-static-member
4QVector<QScriptEngine*> XmlCustomCode::scriptEngines;
5QVector<QScriptValue*> XmlCustomCode::jsFunctions;
6QVector<QScriptValue*> XmlCustomCode::getXmlDataFunctions;
7QVector<QScriptValue*> XmlCustomCode::setXmlDataFunctions;
8
9QScriptValue echo(QScriptContext *context, QScriptEngine*)
10{
11    std::cout << context->argument(0).toString().toUtf8().constData() << std::endl;
12
13    return "";
14}
15
16XmlCustomCode::XmlCustomCode(): numThreads(omp_get_num_procs()*2)
17{
18    // create individual thread script engines if empty
19    if(this->scriptEngines.isEmpty()){
20        this->scriptEngines.reserve(this->numThreads);
21        this->jsFunctions.reserve(this->numThreads);
22        this->getXmlDataFunctions.reserve(this->numThreads);
23        this->setXmlDataFunctions.reserve(this->numThreads);
24
25        QString jsxmlString;
26        QFile jsxmlfile(":/resources/libs/jsxml.js");
27
28        jsxmlfile.open(QFile::ReadOnly | QFile::Text);
29
30        jsxmlString=QTextStream(&jsxmlfile).readAll();
31
32        for(int i=0; i<this->numThreads; i++){
33            this->scriptEngines.append(new QScriptEngine());
34            this->jsFunctions.append(new QScriptValue());
35
36            // main needs to be called so the user code is evaluated
37            // alternatively you can do: myFunc=engine.evaluate('(function main(){})'); myFunc.call();
38            // Note the () around the function
39            this->getXmlDataFunctions.append(new QScriptValue(this->scriptEngines.at(i)->evaluate("(function getXmlData() { return $xmlData; })")));
40            this->setXmlDataFunctions.append(new QScriptValue(this->scriptEngines.at(i)->evaluate("(function setXmlData(newXmlData) { $xmlData=newXmlData; })")));
41
42            // Add echo function so user can debug the code
43            QScriptValue echoFunction = this->scriptEngines.at(i)->newFunction(echo);
44            this->scriptEngines.at(i)->globalObject().setProperty("echo", echoFunction);
45
46            // Add the js library for XmlEditing
47            this->scriptEngines.at(i)->evaluate(jsxmlString);
48        }
49    }
50}
51
52void XmlCustomCode::executeCustomCode(const QString &jsString, const QVector<QString> &filesToProcess, const bool backupsEnabled, const bool verboseEnabled){
53
54    // Reconstruct script functions
55    for(int i=0; i<this->numThreads; i++){
56        *this->jsFunctions[i]=this->scriptEngines.at(i)->evaluate("(function main() {"+jsString+"})");
57    }
58
59    QString currXmlFileString;
60
61    QScriptValue engineResult; // variable to check for js_errors
62    double elapsed_secs=0; // elapsed seconds that a user script took
63    clock_t begin; // seconds that a script started
64
65    // Single tread if small number of files
66    if(filesToProcess.size()<CUSTOM_FILES_PER_THREAD){
67        // Process all XmlFiles
68        for(int i=0; i<filesToProcess.size(); i++){
69
70            customCodeUnwinding(filesToProcess.at(i),currXmlFileString,*this->scriptEngines.at(0),begin,elapsed_secs,engineResult,
71                    *this->jsFunctions.at(0),*this->getXmlDataFunctions.at(0),*this->setXmlDataFunctions.at(0),backupsEnabled,verboseEnabled);
72        }
73    }
74    else{ // Multithread if there are many files
75        // Process all XmlFiles
76#pragma omp parallel for num_threads(this->numThreads) schedule(dynamic)
77        for(int i=0; i<filesToProcess.size()-CUSTOM_FILES_PER_THREAD; i+=CUSTOM_FILES_PER_THREAD){
78
79            const int tid=omp_get_thread_num();
80
81            QString currXmlFileStringThread;
82
83            QScriptValue engineResultThread; // variable to check for js_errors
84            double elapsedSecsThread=0; // elapsed seconds that a user script took
85            clock_t beginThread; // seconds that a script started
86
87            customCodeUnwinding(filesToProcess.at(i),currXmlFileStringThread,*this->scriptEngines.at(tid),beginThread,elapsedSecsThread,engineResultThread,
88                                *this->jsFunctions.at(tid),*this->getXmlDataFunctions.at(tid),*this->setXmlDataFunctions.at(tid),backupsEnabled,verboseEnabled);
89
90            customCodeUnwinding(filesToProcess.at(i+1),currXmlFileStringThread,*this->scriptEngines.at(tid),beginThread,elapsedSecsThread,engineResultThread,
91                                *this->jsFunctions.at(tid),*this->getXmlDataFunctions.at(tid),*this->setXmlDataFunctions.at(tid),backupsEnabled,verboseEnabled);
92        }
93
94        if(filesToProcess.size()%CUSTOM_FILES_PER_THREAD!=0){
95
96            int alreadyProcessedFiles=(filesToProcess.size()/CUSTOM_FILES_PER_THREAD)*CUSTOM_FILES_PER_THREAD;
97
98            for(int i=alreadyProcessedFiles; i<filesToProcess.size(); i++){
99
100                customCodeUnwinding(filesToProcess.at(i),currXmlFileString,*this->scriptEngines.at(0),begin,elapsed_secs,engineResult,
101                        *this->jsFunctions.at(0),*this->getXmlDataFunctions.at(0),*this->setXmlDataFunctions.at(0),backupsEnabled,verboseEnabled);
102            }
103        }
104    }
105}
106
107void XmlCustomCode::displayJsException(QScriptEngine &engine, QScriptValue &engineResult){
108    if (engine.hasUncaughtException()) {
109        UtilXmlTools::displayErrorMessage("@CUSTOM_CODE","Uncaught js exception (user code) at line " +QString::number(engine.uncaughtExceptionLineNumber()) + ":\n" + engineResult.toString());
110    }
111}
Note: See TracBrowser for help on using the repository browser.