blob: 5837c9961d92703ade8b0eea4a2bcd423488210d [file] [log] [blame]
Zack Rusinc6247dd2011-04-17 22:56:58 -04001#include "saverthread.h"
2
José Fonseca9ed67222011-05-24 08:42:59 +01003#include "trace_writer.hpp"
Zack Rusinc6247dd2011-04-17 22:56:58 -04004
5#include <QFile>
6#include <QHash>
7#include <QUrl>
8
9#include <QDebug>
10
11
12static Trace::FunctionSig *
13createFunctionSig(ApiTraceCall *call, unsigned id)
14{
15 Trace::FunctionSig *sig = new Trace::FunctionSig();
16
17 sig->id = id;
18 sig->name = qstrdup(call->name().toLocal8Bit());
19
20 QStringList args = call->argNames();
21 sig->num_args = args.count();
José Fonseca00914322011-05-28 13:10:13 +010022 sig->arg_names = new const char*[args.count()];
Zack Rusinc6247dd2011-04-17 22:56:58 -040023 for (int i = 0; i < args.count(); ++i) {
José Fonseca00914322011-05-28 13:10:13 +010024 sig->arg_names[i] = qstrdup(args[i].toLocal8Bit());
Zack Rusinc6247dd2011-04-17 22:56:58 -040025 }
26
27 return sig;
28}
29
30static void
31deleteFunctionSig(Trace::FunctionSig *sig)
32{
33 for (int i = 0; i < sig->num_args; ++i) {
José Fonseca00914322011-05-28 13:10:13 +010034 delete [] sig->arg_names[i];
Zack Rusinc6247dd2011-04-17 22:56:58 -040035 }
José Fonseca00914322011-05-28 13:10:13 +010036 delete [] sig->arg_names;
Zack Rusinc6247dd2011-04-17 22:56:58 -040037 delete [] sig->name;
38 delete sig;
39}
40
41static Trace::StructSig *
42createStructSig(const ApiStruct &str, unsigned id)
43{
44 ApiStruct::Signature aSig = str.signature();
45
46 Trace::StructSig *sig = new Trace::StructSig();
47 sig->id = id;
48 sig->name = qstrdup(aSig.name.toLocal8Bit());
49 sig->num_members = aSig.memberNames.count();
José Fonseca1b23ed22011-05-28 13:01:16 +010050 char **member_names = new char*[aSig.memberNames.count()];
51 sig->member_names = (const char **)member_names;
Zack Rusinc6247dd2011-04-17 22:56:58 -040052 for (int i = 0; i < aSig.memberNames.count(); ++i) {
José Fonseca1b23ed22011-05-28 13:01:16 +010053 member_names[i] = qstrdup(aSig.memberNames[i].toLocal8Bit());
Zack Rusinc6247dd2011-04-17 22:56:58 -040054 }
55 return sig;
56}
57
58static void
59deleteStructSig(Trace::StructSig *sig)
60{
61 for (int i = 0; i < sig->num_members; ++i) {
José Fonseca1b23ed22011-05-28 13:01:16 +010062 delete [] sig->member_names[i];
Zack Rusinc6247dd2011-04-17 22:56:58 -040063 }
José Fonseca1b23ed22011-05-28 13:01:16 +010064 delete [] sig->member_names;
Zack Rusinc6247dd2011-04-17 22:56:58 -040065 delete [] sig->name;
66 delete sig;
67}
68
69static Trace::EnumSig *
70createEnumSig(const ApiEnum &en, unsigned id)
71{
72 Trace::EnumSig *sig = new Trace::EnumSig();
73
74 sig->id = id;
75 sig->name = qstrdup(en.name().toLocal8Bit());
76 sig->value = en.value().toLongLong();
77
78 return sig;
79}
80
81static void
82deleteEnumSig(Trace::EnumSig *sig)
83{
84 delete [] sig->name;
85 delete sig;
86}
87
88static Trace::BitmaskSig *
89createBitmaskSig(const ApiBitmask &bt, unsigned id)
90{
91 ApiBitmask::Signature bsig = bt.signature();
92 ApiBitmask::Signature::const_iterator itr;
93
94 Trace::BitmaskSig *sig = new Trace::BitmaskSig();
José Fonsecafcfbf172011-05-28 13:20:01 +010095 Trace::BitmaskFlag *flags = new Trace::BitmaskFlag[bsig.count()];
Zack Rusinc6247dd2011-04-17 22:56:58 -040096
97 sig->id = id;
José Fonsecafcfbf172011-05-28 13:20:01 +010098 sig->num_flags = bsig.count();
99 sig->flags = flags;
Zack Rusinc6247dd2011-04-17 22:56:58 -0400100
101 int i = 0;
Zack Rusind809a062011-04-17 23:30:58 -0400102 for (itr = bsig.constBegin(); itr != bsig.constEnd(); ++itr, ++i) {
José Fonsecafcfbf172011-05-28 13:20:01 +0100103 flags[i].name = qstrdup(itr->first.toLocal8Bit());
104 flags[i].value = itr->second;
Zack Rusinc6247dd2011-04-17 22:56:58 -0400105 }
106
107 return sig;
108}
109
110static void
111deleteBitmaskSig(Trace::BitmaskSig *sig)
112{
José Fonsecafcfbf172011-05-28 13:20:01 +0100113 for (int i = 0; i < sig->num_flags; ++i) {
114 delete [] sig->flags[i].name;
Zack Rusinc6247dd2011-04-17 22:56:58 -0400115 }
José Fonsecafcfbf172011-05-28 13:20:01 +0100116 delete [] sig->flags;
Zack Rusinc6247dd2011-04-17 22:56:58 -0400117 delete sig;
118}
119
120static void
José Fonsecaeced7472011-05-28 10:37:12 +0100121writeValue(Trace::Writer &writer, const QVariant &var, unsigned &id)
Zack Rusinc6247dd2011-04-17 22:56:58 -0400122{
123 int arrayType = QMetaType::type("ApiArray");
124 int bitmaskType = QMetaType::type("ApiBitmask");
125 int structType = QMetaType::type("ApiStruct");
126 int pointerType = QMetaType::type("ApiPointer");
127 int enumType = QMetaType::type("ApiEnum");
128 int type = var.userType();
129
130 switch(type) {
131 case QVariant::Bool:
José Fonsecaeced7472011-05-28 10:37:12 +0100132 writer.writeBool(var.toBool());
Zack Rusind809a062011-04-17 23:30:58 -0400133 break;
134 case QVariant::ByteArray: {
135 QByteArray ba = var.toByteArray();
José Fonsecaeced7472011-05-28 10:37:12 +0100136 writer.writeBlob((const void*)ba.constData(), ba.size());
Zack Rusind809a062011-04-17 23:30:58 -0400137 }
138 break;
Zack Rusinc6247dd2011-04-17 22:56:58 -0400139 case QVariant::Double:
José Fonsecaeced7472011-05-28 10:37:12 +0100140 writer.writeDouble(var.toDouble());
Zack Rusind809a062011-04-17 23:30:58 -0400141 break;
142 case QMetaType::Float:
José Fonsecaeced7472011-05-28 10:37:12 +0100143 writer.writeFloat(var.toFloat());
Zack Rusind809a062011-04-17 23:30:58 -0400144 break;
Zack Rusinc6247dd2011-04-17 22:56:58 -0400145 case QVariant::Int:
José Fonsecaeced7472011-05-28 10:37:12 +0100146 writer.writeSInt(var.toInt());
Zack Rusind809a062011-04-17 23:30:58 -0400147 break;
Zack Rusinc6247dd2011-04-17 22:56:58 -0400148 case QVariant::LongLong:
José Fonsecaeced7472011-05-28 10:37:12 +0100149 writer.writeSInt(var.toLongLong());
Zack Rusind809a062011-04-17 23:30:58 -0400150 break;
151 case QVariant::String: {
152 QString str = var.toString();
José Fonsecaeced7472011-05-28 10:37:12 +0100153 writer.writeString(str.toLocal8Bit().constData(), str.length());
Zack Rusind809a062011-04-17 23:30:58 -0400154 }
155 break;
Zack Rusinc6247dd2011-04-17 22:56:58 -0400156 case QVariant::UInt:
José Fonsecaeced7472011-05-28 10:37:12 +0100157 writer.writeUInt(var.toInt());
Zack Rusind809a062011-04-17 23:30:58 -0400158 break;
Zack Rusinc6247dd2011-04-17 22:56:58 -0400159 case QVariant::ULongLong:
José Fonsecaeced7472011-05-28 10:37:12 +0100160 writer.writeUInt(var.toLongLong());
Zack Rusind809a062011-04-17 23:30:58 -0400161 break;
Zack Rusinc6247dd2011-04-17 22:56:58 -0400162 default:
163 if (type == arrayType) {
164 ApiArray array = var.value<ApiArray>();
Zack Rusin77ff98a2011-08-28 22:30:35 -0400165 QVector<QVariant> vals = array.values();
José Fonsecaeced7472011-05-28 10:37:12 +0100166 writer.beginArray(vals.count());
Zack Rusinc6247dd2011-04-17 22:56:58 -0400167 foreach(QVariant el, vals) {
José Fonsecaeced7472011-05-28 10:37:12 +0100168 writer.beginElement();
169 writeValue(writer, el, ++id);
170 writer.endElement();
Zack Rusinc6247dd2011-04-17 22:56:58 -0400171 }
José Fonsecaeced7472011-05-28 10:37:12 +0100172 writer.endArray();
Zack Rusinc6247dd2011-04-17 22:56:58 -0400173 } else if (type == bitmaskType) {
174 ApiBitmask bm = var.value<ApiBitmask>();
175 Trace::BitmaskSig *sig = createBitmaskSig(bm, ++id);
José Fonseca466753b2011-05-28 13:25:55 +0100176 writer.writeBitmask(sig, bm.value());
Zack Rusinc6247dd2011-04-17 22:56:58 -0400177 deleteBitmaskSig(sig);
178 } else if (type == structType) {
179 ApiStruct apiStr = var.value<ApiStruct>();
180 QList<QVariant> vals = apiStr.values();
181 Trace::StructSig *str = createStructSig(apiStr, ++id);
José Fonsecaeced7472011-05-28 10:37:12 +0100182 writer.beginStruct(str);
Zack Rusinc6247dd2011-04-17 22:56:58 -0400183 foreach(QVariant val, vals) {
José Fonsecaeced7472011-05-28 10:37:12 +0100184 writeValue(writer, val, ++id);
Zack Rusinc6247dd2011-04-17 22:56:58 -0400185 }
José Fonsecaeced7472011-05-28 10:37:12 +0100186 writer.endStruct();
Zack Rusinc6247dd2011-04-17 22:56:58 -0400187 deleteStructSig(str);
188 } else if (type == pointerType) {
189 ApiPointer apiPtr = var.value<ApiPointer>();
José Fonsecaeced7472011-05-28 10:37:12 +0100190 //writer.beginArray(1);
191 //writer.beginElement();
192 writer.writeOpaque((const void*)apiPtr.value());
193 //writer.endElement();
194 //writer.endArray();
Zack Rusinc6247dd2011-04-17 22:56:58 -0400195 } else if (type == enumType) {
196 ApiEnum apiEnum = var.value<ApiEnum>();
197 Trace::EnumSig *sig = createEnumSig(apiEnum, ++id);
José Fonsecaeced7472011-05-28 10:37:12 +0100198 writer.writeEnum(sig);
Zack Rusinc6247dd2011-04-17 22:56:58 -0400199 deleteEnumSig(sig);
Zack Rusinc6247dd2011-04-17 22:56:58 -0400200 } else {
201 qWarning()<<"Unsupported write variant : "
202 << QMetaType::typeName(type);
203 }
204 }
Zack Rusinc6247dd2011-04-17 22:56:58 -0400205}
206
Zack Rusinc6247dd2011-04-17 22:56:58 -0400207SaverThread::SaverThread(QObject *parent)
208 : QThread(parent)
209{
210}
211
212void SaverThread::saveFile(const QString &fileName,
Zack Rusin4d0ef5d2011-08-28 22:05:31 -0400213 const QVector<ApiTraceCall*> &calls)
Zack Rusinc6247dd2011-04-17 22:56:58 -0400214{
215 m_fileName = fileName;
216 m_calls = calls;
217 start();
218}
219
220void SaverThread::run()
221{
Zack Rusinc6247dd2011-04-17 22:56:58 -0400222 unsigned id = 0;
José Fonsecaeced7472011-05-28 10:37:12 +0100223 qDebug() << "Saving : " << m_fileName;
224 Trace::Writer writer;
225 writer.open(m_fileName.toLocal8Bit());
Zack Rusinc6247dd2011-04-17 22:56:58 -0400226 for (int i = 0; i < m_calls.count(); ++i) {
227 ApiTraceCall *call = m_calls[i];
228 Trace::FunctionSig *funcSig = createFunctionSig(call, ++id);
José Fonseca466753b2011-05-28 13:25:55 +0100229 unsigned callNo = writer.beginEnter(funcSig);
Zack Rusinc6247dd2011-04-17 22:56:58 -0400230 {
231 //args
Zack Rusinf736a622011-08-28 22:19:46 -0400232 QVector<QVariant> vars = call->arguments();
Zack Rusin2f8bb0b2011-04-18 00:22:50 -0400233 int index = 0;
Zack Rusinc6247dd2011-04-17 22:56:58 -0400234 foreach(QVariant var, vars) {
José Fonsecaeced7472011-05-28 10:37:12 +0100235 writer.beginArg(index++);
236 writeValue(writer, var, ++id);
237 writer.endArg();
Zack Rusinc6247dd2011-04-17 22:56:58 -0400238 }
239 }
José Fonsecaeced7472011-05-28 10:37:12 +0100240 writer.endEnter();
241 writer.beginLeave(callNo);
Zack Rusinc6247dd2011-04-17 22:56:58 -0400242 {
243 QVariant ret = call->returnValue();
244 if (!ret.isNull()) {
José Fonsecaeced7472011-05-28 10:37:12 +0100245 writer.beginReturn();
246 writeValue(writer, ret, ++id);
247 writer.endReturn();
Zack Rusinc6247dd2011-04-17 22:56:58 -0400248 }
249 }
José Fonsecaeced7472011-05-28 10:37:12 +0100250 writer.endLeave();
Zack Rusinc6247dd2011-04-17 22:56:58 -0400251
252 deleteFunctionSig(funcSig);
253 }
José Fonsecaeced7472011-05-28 10:37:12 +0100254 writer.close();
Zack Rusinc6247dd2011-04-17 22:56:58 -0400255
Zack Rusin9af5bff2011-04-18 01:05:50 -0400256 emit traceSaved();
Zack Rusinc6247dd2011-04-17 22:56:58 -0400257}
258
259#include "saverthread.moc"