#include "saverthread.h" #include "trace_writer.hpp" #include "trace_model.hpp" #include "trace_parser.hpp" #include #include #include #include #if 0 static trace::FunctionSig * createFunctionSig(ApiTraceCall *call, unsigned id) { 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->arg_names = new const char*[args.count()]; for (int i = 0; i < args.count(); ++i) { sig->arg_names[i] = qstrdup(args[i].toLocal8Bit()); } return sig; } static void deleteFunctionSig(trace::FunctionSig *sig) { for (int i = 0; i < sig->num_args; ++i) { delete [] sig->arg_names[i]; } delete [] sig->arg_names; delete [] sig->name; delete sig; } static trace::StructSig * createStructSig(const ApiStruct &str, unsigned id) { ApiStruct::Signature aSig = str.signature(); trace::StructSig *sig = new trace::StructSig(); sig->id = id; sig->name = qstrdup(aSig.name.toLocal8Bit()); sig->num_members = aSig.memberNames.count(); char **member_names = new char*[aSig.memberNames.count()]; sig->member_names = (const char **)member_names; for (int i = 0; i < aSig.memberNames.count(); ++i) { member_names[i] = qstrdup(aSig.memberNames[i].toLocal8Bit()); } return sig; } static void deleteStructSig(trace::StructSig *sig) { for (int i = 0; i < sig->num_members; ++i) { delete [] sig->member_names[i]; } delete [] sig->member_names; delete [] sig->name; delete sig; } static trace::EnumSig * createEnumSig(const ApiEnum &en, unsigned id) { trace::EnumSig *sig = new trace::EnumSig(); sig->id = id; sig->name = qstrdup(en.name().toLocal8Bit()); sig->value = en.value().toLongLong(); return sig; } static void deleteEnumSig(trace::EnumSig *sig) { delete [] sig->name; delete sig; } 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::BitmaskFlag *flags = new trace::BitmaskFlag[bsig.count()]; sig->id = id; sig->num_flags = bsig.count(); sig->flags = flags; int i = 0; for (itr = bsig.constBegin(); itr != bsig.constEnd(); ++itr, ++i) { flags[i].name = qstrdup(itr->first.toLocal8Bit()); flags[i].value = itr->second; } return sig; } static void deleteBitmaskSig(trace::BitmaskSig *sig) { for (int i = 0; i < sig->num_flags; ++i) { delete [] sig->flags[i].name; } delete [] sig->flags; delete sig; } static void writeValue(trace::Writer &writer, const QVariant &var, unsigned &id) { int arrayType = QMetaType::type("ApiArray"); int bitmaskType = QMetaType::type("ApiBitmask"); int structType = QMetaType::type("ApiStruct"); int pointerType = QMetaType::type("ApiPointer"); int enumType = QMetaType::type("ApiEnum"); int type = var.userType(); switch(type) { case QVariant::Bool: writer.writeBool(var.toBool()); break; case QVariant::ByteArray: { QByteArray ba = var.toByteArray(); writer.writeBlob((const void*)ba.constData(), ba.size()); } break; case QVariant::Double: writer.writeDouble(var.toDouble()); break; case QMetaType::Float: writer.writeFloat(var.toFloat()); break; case QVariant::Int: writer.writeSInt(var.toInt()); break; case QVariant::LongLong: writer.writeSInt(var.toLongLong()); break; case QVariant::String: { QString str = var.toString(); writer.writeString(str.toLocal8Bit().constData(), str.length()); } break; case QVariant::UInt: writer.writeUInt(var.toInt()); break; case QVariant::ULongLong: writer.writeUInt(var.toLongLong()); break; default: if (type == arrayType) { ApiArray array = var.value(); QVector vals = array.values(); writer.beginArray(vals.count()); foreach(QVariant el, vals) { writer.beginElement(); writeValue(writer, el, ++id); writer.endElement(); } writer.endArray(); } else if (type == bitmaskType) { ApiBitmask bm = var.value(); trace::BitmaskSig *sig = createBitmaskSig(bm, ++id); writer.writeBitmask(sig, bm.value()); deleteBitmaskSig(sig); } else if (type == structType) { ApiStruct apiStr = var.value(); QList vals = apiStr.values(); trace::StructSig *str = createStructSig(apiStr, ++id); writer.beginStruct(str); foreach(QVariant val, vals) { writeValue(writer, val, ++id); } writer.endStruct(); deleteStructSig(str); } else if (type == pointerType) { ApiPointer apiPtr = var.value(); writer.writePointer(apiPtr.value()); } else if (type == enumType) { ApiEnum apiEnum = var.value(); trace::EnumSig *sig = createEnumSig(apiEnum, ++id); writer.writeEnum(sig); deleteEnumSig(sig); } else { qWarning()<<"Unsupported write variant : " << QMetaType::typeName(type); } } } #endif class EditVisitor : public trace::Visitor { public: EditVisitor(const QVariant &variant) : m_variant(variant), m_editedValue(0) {} virtual void visit(trace::Null *val) override { m_editedValue = val; } virtual void visit(trace::Bool *node) override { // Q_ASSERT(m_variant.userType() == QVariant::Bool); bool var = m_variant.toBool(); m_editedValue = new trace::Bool(var); } virtual void visit(trace::SInt *node) override { // Q_ASSERT(m_variant.userType() == QVariant::Int); m_editedValue = new trace::SInt(m_variant.toInt()); } virtual void visit(trace::UInt *node) override { // Q_ASSERT(m_variant.userType() == QVariant::UInt); m_editedValue = new trace::SInt(m_variant.toUInt()); } virtual void visit(trace::Float *node) override { m_editedValue = new trace::Float(m_variant.toFloat()); } virtual void visit(trace::Double *node) override { m_editedValue = new trace::Double(m_variant.toDouble()); } virtual void visit(trace::String *node) override { 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::WString *node) override { QString str = m_variant.toString(); size_t len = str.length(); wchar_t *newString = new wchar_t[len + 1]; str.toWCharArray(newString); newString[len] = 0; m_editedValue = new trace::WString(newString); } virtual void visit(trace::Enum *e) override { m_editedValue = e; } virtual void visit(trace::Bitmask *bitmask) override { m_editedValue = bitmask; } virtual void visit(trace::Struct *str) override { m_editedValue = str; } virtual void visit(trace::Array *array) override { ApiArray apiArray = m_variant.value(); QVector vals = apiArray.values(); trace::Array *newArray = pool.alloc(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 pool.free(newArray); m_editedValue = array; return; } newArray->values[i] = visitor.value(); } m_editedValue = newArray; } virtual void visit(trace::Blob *blob) override { m_editedValue = blob; } virtual void visit(trace::Pointer *ptr) override { 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()) { pool.free(origValue); call->args[index].value = visitor.value(); } } SaverThread::SaverThread(QObject *parent) : QThread(parent) { } void SaverThread::saveFile(const QString &writeFileName, const QString &readFileName, const QSet &editedCalls) { m_writeFileName = writeFileName; m_readFileName = readFileName; m_editedCalls = editedCalls; start(); } void SaverThread::run() { qDebug() << "Saving " << m_readFileName << ", to " << m_writeFileName; QMap 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 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); } pool.free(call); } writer.close(); emit traceSaved(); } #include "saverthread.moc"