1 #include "saverthread.h"
3 #include "trace_writer.hpp"
12 static Trace::FunctionSig *
13 createFunctionSig(ApiTraceCall *call, unsigned id)
15 Trace::FunctionSig *sig = new Trace::FunctionSig();
18 sig->name = qstrdup(call->name().toLocal8Bit());
20 QStringList args = call->argNames();
21 sig->num_args = args.count();
22 sig->arg_names = new const char*[args.count()];
23 for (int i = 0; i < args.count(); ++i) {
24 sig->arg_names[i] = qstrdup(args[i].toLocal8Bit());
31 deleteFunctionSig(Trace::FunctionSig *sig)
33 for (int i = 0; i < sig->num_args; ++i) {
34 delete [] sig->arg_names[i];
36 delete [] sig->arg_names;
41 static Trace::StructSig *
42 createStructSig(const ApiStruct &str, unsigned id)
44 ApiStruct::Signature aSig = str.signature();
46 Trace::StructSig *sig = new Trace::StructSig();
48 sig->name = qstrdup(aSig.name.toLocal8Bit());
49 sig->num_members = aSig.memberNames.count();
50 char **member_names = new char*[aSig.memberNames.count()];
51 sig->member_names = (const char **)member_names;
52 for (int i = 0; i < aSig.memberNames.count(); ++i) {
53 member_names[i] = qstrdup(aSig.memberNames[i].toLocal8Bit());
59 deleteStructSig(Trace::StructSig *sig)
61 for (int i = 0; i < sig->num_members; ++i) {
62 delete [] sig->member_names[i];
64 delete [] sig->member_names;
69 static Trace::EnumSig *
70 createEnumSig(const ApiEnum &en, unsigned id)
72 Trace::EnumSig *sig = new Trace::EnumSig();
75 sig->name = qstrdup(en.name().toLocal8Bit());
76 sig->value = en.value().toLongLong();
82 deleteEnumSig(Trace::EnumSig *sig)
88 static Trace::BitmaskSig *
89 createBitmaskSig(const ApiBitmask &bt, unsigned id)
91 ApiBitmask::Signature bsig = bt.signature();
92 ApiBitmask::Signature::const_iterator itr;
94 Trace::BitmaskSig *sig = new Trace::BitmaskSig();
95 Trace::BitmaskFlag *flags = new Trace::BitmaskFlag[bsig.count()];
98 sig->num_flags = bsig.count();
102 for (itr = bsig.constBegin(); itr != bsig.constEnd(); ++itr, ++i) {
103 flags[i].name = qstrdup(itr->first.toLocal8Bit());
104 flags[i].value = itr->second;
111 deleteBitmaskSig(Trace::BitmaskSig *sig)
113 for (int i = 0; i < sig->num_flags; ++i) {
114 delete [] sig->flags[i].name;
116 delete [] sig->flags;
121 writeValue(Trace::Writer &writer, const QVariant &var, unsigned &id)
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();
132 writer.writeBool(var.toBool());
134 case QVariant::ByteArray: {
135 QByteArray ba = var.toByteArray();
136 writer.writeBlob((const void*)ba.constData(), ba.size());
139 case QVariant::Double:
140 writer.writeDouble(var.toDouble());
142 case QMetaType::Float:
143 writer.writeFloat(var.toFloat());
146 writer.writeSInt(var.toInt());
148 case QVariant::LongLong:
149 writer.writeSInt(var.toLongLong());
151 case QVariant::String: {
152 QString str = var.toString();
153 writer.writeString(str.toLocal8Bit().constData(), str.length());
157 writer.writeUInt(var.toInt());
159 case QVariant::ULongLong:
160 writer.writeUInt(var.toLongLong());
163 if (type == arrayType) {
164 ApiArray array = var.value<ApiArray>();
165 QVector<QVariant> vals = array.values();
166 writer.beginArray(vals.count());
167 foreach(QVariant el, vals) {
168 writer.beginElement();
169 writeValue(writer, el, ++id);
173 } else if (type == bitmaskType) {
174 ApiBitmask bm = var.value<ApiBitmask>();
175 Trace::BitmaskSig *sig = createBitmaskSig(bm, ++id);
176 writer.writeBitmask(sig, bm.value());
177 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);
182 writer.beginStruct(str);
183 foreach(QVariant val, vals) {
184 writeValue(writer, val, ++id);
187 deleteStructSig(str);
188 } else if (type == pointerType) {
189 ApiPointer apiPtr = var.value<ApiPointer>();
190 //writer.beginArray(1);
191 //writer.beginElement();
192 writer.writeOpaque((const void*)apiPtr.value());
193 //writer.endElement();
195 } else if (type == enumType) {
196 ApiEnum apiEnum = var.value<ApiEnum>();
197 Trace::EnumSig *sig = createEnumSig(apiEnum, ++id);
198 writer.writeEnum(sig);
201 qWarning()<<"Unsupported write variant : "
202 << QMetaType::typeName(type);
207 SaverThread::SaverThread(QObject *parent)
212 void SaverThread::saveFile(const QString &fileName,
213 const QVector<ApiTraceCall*> &calls)
215 m_fileName = fileName;
220 void SaverThread::run()
223 qDebug() << "Saving : " << m_fileName;
224 Trace::Writer writer;
225 writer.open(m_fileName.toLocal8Bit());
226 for (int i = 0; i < m_calls.count(); ++i) {
227 ApiTraceCall *call = m_calls[i];
228 Trace::FunctionSig *funcSig = createFunctionSig(call, ++id);
229 unsigned callNo = writer.beginEnter(funcSig);
232 QVector<QVariant> vars = call->arguments();
234 foreach(QVariant var, vars) {
235 writer.beginArg(index++);
236 writeValue(writer, var, ++id);
241 writer.beginLeave(callNo);
243 QVariant ret = call->returnValue();
245 writer.beginReturn();
246 writeValue(writer, ret, ++id);
252 deleteFunctionSig(funcSig);
259 #include "saverthread.moc"