1 #include "saverthread.h"
3 #include "trace_writer.hpp"
4 #include "trace_model.hpp"
5 #include "trace_parser.hpp"
14 static trace::FunctionSig *
15 createFunctionSig(ApiTraceCall *call, unsigned id)
17 trace::FunctionSig *sig = new trace::FunctionSig();
20 sig->name = qstrdup(call->name().toLocal8Bit());
22 QStringList args = call->argNames();
23 sig->num_args = args.count();
24 sig->arg_names = new const char*[args.count()];
25 for (int i = 0; i < args.count(); ++i) {
26 sig->arg_names[i] = qstrdup(args[i].toLocal8Bit());
33 deleteFunctionSig(trace::FunctionSig *sig)
35 for (int i = 0; i < sig->num_args; ++i) {
36 delete [] sig->arg_names[i];
38 delete [] sig->arg_names;
43 static trace::StructSig *
44 createStructSig(const ApiStruct &str, unsigned id)
46 ApiStruct::Signature aSig = str.signature();
48 trace::StructSig *sig = new trace::StructSig();
50 sig->name = qstrdup(aSig.name.toLocal8Bit());
51 sig->num_members = aSig.memberNames.count();
52 char **member_names = new char*[aSig.memberNames.count()];
53 sig->member_names = (const char **)member_names;
54 for (int i = 0; i < aSig.memberNames.count(); ++i) {
55 member_names[i] = qstrdup(aSig.memberNames[i].toLocal8Bit());
61 deleteStructSig(trace::StructSig *sig)
63 for (int i = 0; i < sig->num_members; ++i) {
64 delete [] sig->member_names[i];
66 delete [] sig->member_names;
71 static trace::EnumSig *
72 createEnumSig(const ApiEnum &en, unsigned id)
74 trace::EnumSig *sig = new trace::EnumSig();
77 sig->name = qstrdup(en.name().toLocal8Bit());
78 sig->value = en.value().toLongLong();
84 deleteEnumSig(trace::EnumSig *sig)
90 static trace::BitmaskSig *
91 createBitmaskSig(const ApiBitmask &bt, unsigned id)
93 ApiBitmask::Signature bsig = bt.signature();
94 ApiBitmask::Signature::const_iterator itr;
96 trace::BitmaskSig *sig = new trace::BitmaskSig();
97 trace::BitmaskFlag *flags = new trace::BitmaskFlag[bsig.count()];
100 sig->num_flags = bsig.count();
104 for (itr = bsig.constBegin(); itr != bsig.constEnd(); ++itr, ++i) {
105 flags[i].name = qstrdup(itr->first.toLocal8Bit());
106 flags[i].value = itr->second;
113 deleteBitmaskSig(trace::BitmaskSig *sig)
115 for (int i = 0; i < sig->num_flags; ++i) {
116 delete [] sig->flags[i].name;
118 delete [] sig->flags;
123 writeValue(trace::Writer &writer, const QVariant &var, unsigned &id)
125 int arrayType = QMetaType::type("ApiArray");
126 int bitmaskType = QMetaType::type("ApiBitmask");
127 int structType = QMetaType::type("ApiStruct");
128 int pointerType = QMetaType::type("ApiPointer");
129 int enumType = QMetaType::type("ApiEnum");
130 int type = var.userType();
134 writer.writeBool(var.toBool());
136 case QVariant::ByteArray: {
137 QByteArray ba = var.toByteArray();
138 writer.writeBlob((const void*)ba.constData(), ba.size());
141 case QVariant::Double:
142 writer.writeDouble(var.toDouble());
144 case QMetaType::Float:
145 writer.writeFloat(var.toFloat());
148 writer.writeSInt(var.toInt());
150 case QVariant::LongLong:
151 writer.writeSInt(var.toLongLong());
153 case QVariant::String: {
154 QString str = var.toString();
155 writer.writeString(str.toLocal8Bit().constData(), str.length());
159 writer.writeUInt(var.toInt());
161 case QVariant::ULongLong:
162 writer.writeUInt(var.toLongLong());
165 if (type == arrayType) {
166 ApiArray array = var.value<ApiArray>();
167 QVector<QVariant> vals = array.values();
168 writer.beginArray(vals.count());
169 foreach(QVariant el, vals) {
170 writer.beginElement();
171 writeValue(writer, el, ++id);
175 } else if (type == bitmaskType) {
176 ApiBitmask bm = var.value<ApiBitmask>();
177 trace::BitmaskSig *sig = createBitmaskSig(bm, ++id);
178 writer.writeBitmask(sig, bm.value());
179 deleteBitmaskSig(sig);
180 } else if (type == structType) {
181 ApiStruct apiStr = var.value<ApiStruct>();
182 QList<QVariant> vals = apiStr.values();
183 trace::StructSig *str = createStructSig(apiStr, ++id);
184 writer.beginStruct(str);
185 foreach(QVariant val, vals) {
186 writeValue(writer, val, ++id);
189 deleteStructSig(str);
190 } else if (type == pointerType) {
191 ApiPointer apiPtr = var.value<ApiPointer>();
192 writer.writePointer(apiPtr.value());
193 } else if (type == enumType) {
194 ApiEnum apiEnum = var.value<ApiEnum>();
195 trace::EnumSig *sig = createEnumSig(apiEnum, ++id);
196 writer.writeEnum(sig);
199 qWarning()<<"Unsupported write variant : "
200 << QMetaType::typeName(type);
206 class EditVisitor : public trace::Visitor
209 EditVisitor(const QVariant &variant)
210 : m_variant(variant),
213 virtual void visit(trace::Null *val)
218 virtual void visit(trace::Bool *node)
220 // Q_ASSERT(m_variant.userType() == QVariant::Bool);
221 bool var = m_variant.toBool();
222 m_editedValue = new trace::Bool(var);
225 virtual void visit(trace::SInt *node)
227 // Q_ASSERT(m_variant.userType() == QVariant::Int);
228 m_editedValue = new trace::SInt(m_variant.toInt());
231 virtual void visit(trace::UInt *node)
233 // Q_ASSERT(m_variant.userType() == QVariant::UInt);
234 m_editedValue = new trace::SInt(m_variant.toUInt());
237 virtual void visit(trace::Float *node)
239 m_editedValue = new trace::Float(m_variant.toFloat());
242 virtual void visit(trace::Double *node)
244 m_editedValue = new trace::Double(m_variant.toDouble());
247 virtual void visit(trace::String *node)
249 QString str = m_variant.toString();
250 char *newString = new char[str.length() + 1];
251 QByteArray ba = str.toLocal8Bit();
252 strcpy(newString, ba.constData());
253 m_editedValue = new trace::String(newString);
256 virtual void visit(trace::Enum *e)
261 virtual void visit(trace::Bitmask *bitmask)
263 m_editedValue = bitmask;
266 virtual void visit(trace::Struct *str)
271 virtual void visit(trace::Array *array)
273 ApiArray apiArray = m_variant.value<ApiArray>();
274 QVector<QVariant> vals = apiArray.values();
276 trace::Array *newArray = new trace::Array(vals.count());
277 for (int i = 0; i < vals.count(); ++i) {
278 EditVisitor visitor(vals[i]);
279 array->values[i]->visit(visitor);
280 if (array->values[i] == visitor.value()) {
283 m_editedValue = array;
287 newArray->values[i] = visitor.value();
289 m_editedValue = newArray;
292 virtual void visit(trace::Blob *blob)
294 m_editedValue = blob;
297 virtual void visit(trace::Pointer *ptr)
302 trace::Value *value() const
304 return m_editedValue;
308 trace::Value *m_editedValue;
312 overwriteValue(trace::Call *call, const QVariant &val, int index)
314 EditVisitor visitor(val);
315 trace::Value *origValue = call->args[index].value;
316 origValue->visit(visitor);
318 if (visitor.value() && origValue != visitor.value()) {
320 call->args[index].value = visitor.value();
324 SaverThread::SaverThread(QObject *parent)
329 void SaverThread::saveFile(const QString &writeFileName,
330 const QString &readFileName,
331 const QSet<ApiTraceCall*> &editedCalls)
333 m_writeFileName = writeFileName;
334 m_readFileName = readFileName;
335 m_editedCalls = editedCalls;
339 void SaverThread::run()
341 qDebug() << "Saving " << m_readFileName
342 << ", to " << m_writeFileName;
343 QMap<int, ApiTraceCall*> callIndexMap;
345 foreach(ApiTraceCall *call, m_editedCalls) {
346 callIndexMap.insert(call->index(), call);
349 trace::Writer writer;
350 writer.open(m_writeFileName.toLocal8Bit());
352 trace::Parser parser;
353 parser.open(m_readFileName.toLocal8Bit());
356 while ((call = parser.parse_call())) {
357 if (callIndexMap.contains(call->no)) {
358 QVector<QVariant> values = callIndexMap[call->no]->editedValues();
359 for (int i = 0; i < values.count(); ++i) {
360 const QVariant &val = values[i];
361 overwriteValue(call, val, i);
363 writer.writeCall(call);
365 writer.writeCall(call);
374 #include "saverthread.moc"