]> git.cworth.org Git - apitrace/blobdiff - gui/saverthread.cpp
Use skiplist-based FastCallSet within trace::CallSet
[apitrace] / gui / saverthread.cpp
index ac726a1d8c32ae2551d551666a7a4ead8ead09e1..4ad83c5876c5caf1267d80cc8c8029bdc18b7c93 100644 (file)
@@ -1,6 +1,8 @@
 #include "saverthread.h"
 
-#include "trace_write.hpp"
+#include "trace_writer.hpp"
+#include "trace_model.hpp"
+#include "trace_parser.hpp"
 
 #include <QFile>
 #include <QHash>
 
 #include <QDebug>
 
-
-static Trace::FunctionSig *
+#if 0
+static trace::FunctionSig *
 createFunctionSig(ApiTraceCall *call, unsigned id)
 {
-    Trace::FunctionSig *sig = new Trace::FunctionSig();
+    trace::FunctionSig *sig = new trace::FunctionSig();
 
     sig->id = id;
     sig->name = qstrdup(call->name().toLocal8Bit());
 
     QStringList args = call->argNames();
     sig->num_args = args.count();
-    sig->args = new const char*[args.count()];
+    sig->arg_names = new const char*[args.count()];
     for (int i = 0; i < args.count(); ++i) {
-        sig->args[i] = qstrdup(args[i].toLocal8Bit());
+        sig->arg_names[i] = qstrdup(args[i].toLocal8Bit());
     }
 
     return sig;
 }
 
 static void
-deleteFunctionSig(Trace::FunctionSig *sig)
+deleteFunctionSig(trace::FunctionSig *sig)
 {
     for (int i = 0; i < sig->num_args; ++i) {
-        delete [] sig->args[i];
+        delete [] sig->arg_names[i];
     }
-    delete [] sig->args;
+    delete [] sig->arg_names;
     delete [] sig->name;
     delete sig;
 }
 
-static Trace::StructSig *
+static trace::StructSig *
 createStructSig(const ApiStruct &str, unsigned id)
 {
     ApiStruct::Signature aSig = str.signature();
 
-    Trace::StructSig *sig = new Trace::StructSig();
+    trace::StructSig *sig = new trace::StructSig();
     sig->id = id;
     sig->name = qstrdup(aSig.name.toLocal8Bit());
     sig->num_members = aSig.memberNames.count();
-    char **members = new char*[aSig.memberNames.count()];
-    sig->members = (const char **)members;
+    char **member_names = new char*[aSig.memberNames.count()];
+    sig->member_names = (const char **)member_names;
     for (int i = 0; i < aSig.memberNames.count(); ++i) {
-        members[i] = qstrdup(aSig.memberNames[i].toLocal8Bit());
+        member_names[i] = qstrdup(aSig.memberNames[i].toLocal8Bit());
     }
     return sig;
 }
 
 static void
-deleteStructSig(Trace::StructSig *sig)
+deleteStructSig(trace::StructSig *sig)
 {
     for (int i = 0; i < sig->num_members; ++i) {
-        delete [] sig->members[i];
+        delete [] sig->member_names[i];
     }
-    delete [] sig->members;
+    delete [] sig->member_names;
     delete [] sig->name;
     delete sig;
 }
 
-static Trace::EnumSig *
+static trace::EnumSig *
 createEnumSig(const ApiEnum &en, unsigned id)
 {
-    Trace::EnumSig *sig = new Trace::EnumSig();
+    trace::EnumSig *sig = new trace::EnumSig();
 
     sig->id = id;
     sig->name = qstrdup(en.name().toLocal8Bit());
@@ -79,46 +81,46 @@ createEnumSig(const ApiEnum &en, unsigned id)
 }
 
 static void
-deleteEnumSig(Trace::EnumSig *sig)
+deleteEnumSig(trace::EnumSig *sig)
 {
     delete [] sig->name;
     delete sig;
 }
 
-static Trace::BitmaskSig *
+static trace::BitmaskSig *
 createBitmaskSig(const ApiBitmask &bt, unsigned id)
 {
     ApiBitmask::Signature bsig = bt.signature();
     ApiBitmask::Signature::const_iterator itr;
 
-    Trace::BitmaskSig *sig = new Trace::BitmaskSig();
-    Trace::BitmaskVal *values = new Trace::BitmaskVal[bsig.count()];
+    trace::BitmaskSig *sig = new trace::BitmaskSig();
+    trace::BitmaskFlag *flags = new trace::BitmaskFlag[bsig.count()];
 
     sig->id = id;
-    sig->count = bsig.count();
-    sig->values = values;
+    sig->num_flags = bsig.count();
+    sig->flags = flags;
 
     int i = 0;
     for (itr = bsig.constBegin(); itr != bsig.constEnd(); ++itr, ++i) {
-        values[i].name = qstrdup(itr->first.toLocal8Bit());
-        values[i].value = itr->second;
+        flags[i].name = qstrdup(itr->first.toLocal8Bit());
+        flags[i].value = itr->second;
     }
 
     return sig;
 }
 
 static void
-deleteBitmaskSig(Trace::BitmaskSig *sig)
+deleteBitmaskSig(trace::BitmaskSig *sig)
 {
-    for (int i = 0; i < sig->count; ++i) {
-        delete [] sig->values[i].name;
+    for (int i = 0; i < sig->num_flags; ++i) {
+        delete [] sig->flags[i].name;
     }
-    delete [] sig->values;
+    delete [] sig->flags;
     delete sig;
 }
 
 static void
-writeValue(const QVariant &var, unsigned &id)
+writeValue(trace::Writer &writer, const QVariant &var, unsigned &id)
 {
     int arrayType   = QMetaType::type("ApiArray");
     int bitmaskType = QMetaType::type("ApiBitmask");
@@ -129,73 +131,69 @@ writeValue(const QVariant &var, unsigned &id)
 
     switch(type) {
     case QVariant::Bool:
-        Trace::LiteralBool(var.toBool());
+        writer.writeBool(var.toBool());
         break;
     case QVariant::ByteArray: {
         QByteArray ba = var.toByteArray();
-        Trace::LiteralBlob((const void*)ba.constData(), ba.size());
+        writer.writeBlob((const void*)ba.constData(), ba.size());
     }
         break;
     case QVariant::Double:
-        Trace::LiteralFloat(var.toDouble());
+        writer.writeDouble(var.toDouble());
         break;
     case QMetaType::Float:
-        Trace::LiteralFloat(var.toFloat());
+        writer.writeFloat(var.toFloat());
         break;
     case QVariant::Int:
-        Trace::LiteralSInt(var.toInt());
+        writer.writeSInt(var.toInt());
         break;
     case QVariant::LongLong:
-        Trace::LiteralSInt(var.toLongLong());
+        writer.writeSInt(var.toLongLong());
         break;
     case QVariant::String: {
         QString str = var.toString();
-        Trace::LiteralString(str.toLocal8Bit().constData(), str.length());
+        writer.writeString(str.toLocal8Bit().constData(), str.length());
     }
         break;
     case QVariant::UInt:
-        Trace::LiteralUInt(var.toInt());
+        writer.writeUInt(var.toInt());
         break;
     case QVariant::ULongLong:
-        Trace::LiteralUInt(var.toLongLong());
+        writer.writeUInt(var.toLongLong());
         break;
     default:
         if (type == arrayType) {
             ApiArray array = var.value<ApiArray>();
-            QList<QVariant> vals = array.values();
-            Trace::BeginArray(vals.count());
+            QVector<QVariant> vals = array.values();
+            writer.beginArray(vals.count());
             foreach(QVariant el, vals) {
-                Trace::BeginElement();
-                writeValue(el, ++id);
-                Trace::EndElement();
+                writer.beginElement();
+                writeValue(writer, el, ++id);
+                writer.endElement();
             }
-            Trace::EndArray();
+            writer.endArray();
         } else if (type == bitmaskType) {
             ApiBitmask bm = var.value<ApiBitmask>();
-            Trace::BitmaskSig *sig = createBitmaskSig(bm, ++id);
-            LiteralBitmask(*sig, bm.value());
+            trace::BitmaskSig *sig = createBitmaskSig(bm, ++id);
+            writer.writeBitmask(sig, bm.value());
             deleteBitmaskSig(sig);
         } else if (type == structType) {
             ApiStruct apiStr = var.value<ApiStruct>();
             QList<QVariant> vals = apiStr.values();
-            Trace::StructSig *str = createStructSig(apiStr, ++id);
-            Trace::BeginStruct(str);
+            trace::StructSig *str = createStructSig(apiStr, ++id);
+            writer.beginStruct(str);
             foreach(QVariant val, vals) {
-                writeValue(val, ++id);
+                writeValue(writer, val, ++id);
             }
-            Trace::EndStruct();
+            writer.endStruct();
             deleteStructSig(str);
         } else if (type == pointerType) {
             ApiPointer apiPtr = var.value<ApiPointer>();
-            //Trace::BeginArray(1);
-            //Trace::BeginElement();
-            Trace::LiteralOpaque((const void*)apiPtr.value());
-            //Trace::EndElement();
-            //Trace::EndArray();
+            writer.writePointer(apiPtr.value());
         } else if (type == enumType) {
             ApiEnum apiEnum = var.value<ApiEnum>();
-            Trace::EnumSig *sig = createEnumSig(apiEnum, ++id);
-            Trace::LiteralEnum(sig);
+            trace::EnumSig *sig = createEnumSig(apiEnum, ++id);
+            writer.writeEnum(sig);
             deleteEnumSig(sig);
         } else {
             qWarning()<<"Unsupported write variant : "
@@ -203,55 +201,172 @@ writeValue(const QVariant &var, unsigned &id)
         }
     }
 }
+#endif
+
+class EditVisitor : public trace::Visitor
+{
+public:
+    EditVisitor(const QVariant &variant)
+        : m_variant(variant),
+          m_editedValue(0)
+    {}
+    virtual void visit(trace::Null *val)
+    {
+        m_editedValue = val;
+    }
+
+    virtual void visit(trace::Bool *node)
+    {
+//        Q_ASSERT(m_variant.userType() == QVariant::Bool);
+        bool var = m_variant.toBool();
+        m_editedValue = new trace::Bool(var);
+    }
+
+    virtual void visit(trace::SInt *node)
+    {
+//        Q_ASSERT(m_variant.userType() == QVariant::Int);
+        m_editedValue = new trace::SInt(m_variant.toInt());
+    }
+
+    virtual void visit(trace::UInt *node)
+    {
+//        Q_ASSERT(m_variant.userType() == QVariant::UInt);
+        m_editedValue = new trace::SInt(m_variant.toUInt());
+    }
+
+    virtual void visit(trace::Float *node)
+    {
+        m_editedValue = new trace::Float(m_variant.toFloat());
+    }
+
+    virtual void visit(trace::Double *node)
+    {
+        m_editedValue = new trace::Double(m_variant.toDouble());
+    }
+
+    virtual void visit(trace::String *node)
+    {
+        QString str = m_variant.toString();
+        char *newString = new char[str.length() + 1];
+        QByteArray ba = str.toLocal8Bit();
+        strcpy(newString, ba.constData());
+        m_editedValue = new trace::String(newString);
+    }
+
+    virtual void visit(trace::Enum *e)
+    {
+        m_editedValue = e;
+    }
+
+    virtual void visit(trace::Bitmask *bitmask)
+    {
+        m_editedValue = bitmask;
+    }
+
+    virtual void visit(trace::Struct *str)
+    {
+        m_editedValue = str;
+    }
+
+    virtual void visit(trace::Array *array)
+    {
+        ApiArray apiArray = m_variant.value<ApiArray>();
+        QVector<QVariant> vals = apiArray.values();
+
+        trace::Array *newArray = new trace::Array(vals.count());
+        for (int i = 0; i < vals.count(); ++i) {
+            EditVisitor visitor(vals[i]);
+            array->values[i]->visit(visitor);
+            if (array->values[i] == visitor.value()) {
+                //non-editabled
+                delete newArray;
+                m_editedValue = array;
+                return;
+            }
+
+            newArray->values[i] = visitor.value();
+        }
+        m_editedValue = newArray;
+    }
+
+    virtual void visit(trace::Blob *blob)
+    {
+        m_editedValue = blob;
+    }
+
+    virtual void visit(trace::Pointer *ptr)
+    {
+        m_editedValue = ptr;
+    }
+
+    trace::Value *value() const
+    {
+        return m_editedValue;
+    }
+private:
+    QVariant m_variant;
+    trace::Value *m_editedValue;
+};
+
+static void
+overwriteValue(trace::Call *call, const QVariant &val, int index)
+{
+    EditVisitor visitor(val);
+    trace::Value *origValue = call->args[index].value;
+    origValue->visit(visitor);
+
+    if (visitor.value() && origValue != visitor.value()) {
+        delete origValue;
+        call->args[index].value = visitor.value();
+    }
+}
 
 SaverThread::SaverThread(QObject *parent)
     : QThread(parent)
 {
 }
 
-void SaverThread::saveFile(const QString &fileName,
-                           const QList<ApiTraceCall*> &calls)
+void SaverThread::saveFile(const QString &writeFileName,
+                           const QString &readFileName,
+                           const QSet<ApiTraceCall*> &editedCalls)
 {
-    m_fileName = fileName;
-    m_calls = calls;
+    m_writeFileName = writeFileName;
+    m_readFileName = readFileName;
+    m_editedCalls = editedCalls;
     start();
 }
 
 void SaverThread::run()
 {
-    qputenv("TRACE_PATH", m_fileName.toLocal8Bit());
-    unsigned id = 0;
-
-    Trace::Open();
-    for (int i = 0; i < m_calls.count(); ++i) {
-        ApiTraceCall *call = m_calls[i];
-        Trace::FunctionSig *funcSig = createFunctionSig(call, ++id);
-        unsigned callNo = Trace::BeginEnter(*funcSig);
-        {
-            //args
-            QVariantList vars = call->arguments();
-            int index = 0;
-            foreach(QVariant var, vars) {
-                Trace::BeginArg(index++);
-                writeValue(var, ++id);
-                Trace::EndArg();
-            }
-        }
-        Trace::EndEnter();
-        Trace::BeginLeave(callNo);
-        {
-            QVariant ret = call->returnValue();
-            if (!ret.isNull()) {
-                Trace::BeginReturn();
-                writeValue(ret, ++id);
-                Trace::EndReturn();
+    qDebug() << "Saving  " << m_readFileName
+             << ", to " << m_writeFileName;
+    QMap<int, ApiTraceCall*> callIndexMap;
+
+    foreach(ApiTraceCall *call, m_editedCalls) {
+        callIndexMap.insert(call->index(), call);
+    }
+
+    trace::Writer writer;
+    writer.open(m_writeFileName.toLocal8Bit());
+
+    trace::Parser parser;
+    parser.open(m_readFileName.toLocal8Bit());
+
+    trace::Call *call;
+    while ((call = parser.parse_call())) {
+        if (callIndexMap.contains(call->no)) {
+            QVector<QVariant> values = callIndexMap[call->no]->editedValues();
+            for (int i = 0; i < values.count(); ++i) {
+                const QVariant &val = values[i];
+                overwriteValue(call, val, i);
             }
+            writer.writeCall(call);
+        } else {
+            writer.writeCall(call);
         }
-        Trace::EndLeave();
-
-        deleteFunctionSig(funcSig);
     }
-    Trace::Close();
+
+    writer.close();
 
     emit traceSaved();
 }