X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=gui%2Ftraceloader.cpp;h=108d220e0a642654c6084c8920d3db2191fc6922;hb=1a9f7af32205d900c88fef0b544546eb0d7c84ee;hp=b6eba6a0247af29645d54b4f76c20b67f255336c;hpb=ac92a2115ab3c759add836e115f108c945e0195b;p=apitrace diff --git a/gui/traceloader.cpp b/gui/traceloader.cpp index b6eba6a..108d220 100644 --- a/gui/traceloader.cpp +++ b/gui/traceloader.cpp @@ -1,5 +1,6 @@ #include "traceloader.h" +#include "apitrace.h" #include #include @@ -53,32 +54,9 @@ void TraceLoader::loadTrace(const QString &filename) emit finishedParsing(); } -void TraceLoader::loadFrame(int frameIdx) +void TraceLoader::loadFrame(ApiTraceFrame *currentFrame) { - if (m_parser.supportsOffsets()) { - int numOfCalls = numberOfCallsInFrame(frameIdx); - if (numOfCalls) { - const FrameOffset &frameOffset = m_frameOffsets[frameIdx]; - std::vector calls(numOfCalls); - m_parser.setCurrentOffset(frameOffset.start); - m_parser.setCurrentCallNumber(frameOffset.callNumber); - - Trace::Call *call; - int parsedCalls = 0; - while ((call = m_parser.parse_call())) { - - calls[parsedCalls] = call; - ++parsedCalls; - - if (isCallAFrameMarker(call)) { - break; - } - - } - assert(parsedCalls == numOfCalls); - // emit parsedFrame(); - } - } + fetchFrameContents(currentFrame); } void TraceLoader::setFrameMarker(ApiTrace::FrameMarker marker) @@ -111,16 +89,16 @@ bool TraceLoader::isCallAFrameMarker(const Trace::Call *call) const int TraceLoader::numberOfFrames() const { - return m_frameOffsets.size(); + return m_frameBookmarks.size(); } int TraceLoader::numberOfCallsInFrame(int frameIdx) const { - if (frameIdx > m_frameOffsets.size()) { + if (frameIdx > m_frameBookmarks.size()) { return 0; } - FrameOffsets::const_iterator itr = - m_frameOffsets.find(frameIdx); + FrameBookmarks::const_iterator itr = + m_frameBookmarks.find(frameIdx); return itr->numberOfCalls; } @@ -149,56 +127,52 @@ void TraceLoader::scanTrace() ApiTraceFrame *currentFrame = 0; Trace::Call *call; - Trace::File::Offset startOffset; + Trace::ParseBookmark startBookmark; int numOfFrames = 0; int numOfCalls = 0; - unsigned callNum = 0; int lastPercentReport = 0; - startOffset = m_parser.currentOffset(); - callNum = m_parser.currentCallNumber(); + m_parser.getBookmark(startBookmark); while ((call = m_parser.scan_call())) { ++numOfCalls; if (isCallAFrameMarker(call)) { - Trace::File::Offset endOffset = m_parser.currentOffset(); - FrameOffset frameOffset(startOffset); - frameOffset.numberOfCalls = numOfCalls; - frameOffset.callNumber = callNum; + FrameBookmark frameBookmark(startBookmark); + frameBookmark.numberOfCalls = numOfCalls; currentFrame = new ApiTraceFrame(); currentFrame->number = numOfFrames; currentFrame->setNumChildren(numOfCalls); + currentFrame->setLastCallIndex(call->no); frames.append(currentFrame); - m_frameOffsets[numOfFrames] = frameOffset; + m_createdFrames.append(currentFrame); + m_frameBookmarks[numOfFrames] = frameBookmark; ++numOfFrames; if (m_parser.percentRead() - lastPercentReport >= 5) { emit parsed(m_parser.percentRead()); lastPercentReport = m_parser.percentRead(); } - startOffset = endOffset; - callNum = m_parser.currentCallNumber(); + m_parser.getBookmark(startBookmark); numOfCalls = 0; } - //call->dump(std::cout, color); delete call; } if (numOfCalls) { - // Trace::File::Offset endOffset = m_parser.currentOffset(); - FrameOffset frameOffset(startOffset); - frameOffset.numberOfCalls = numOfCalls; - frameOffset.callNumber = callNum; + //Trace::File::Bookmark endBookmark = m_parser.currentBookmark(); + FrameBookmark frameBookmark(startBookmark); + frameBookmark.numberOfCalls = numOfCalls; currentFrame = new ApiTraceFrame(); currentFrame->number = numOfFrames; currentFrame->setNumChildren(numOfCalls); frames.append(currentFrame); - m_frameOffsets[numOfFrames] = frameOffset; + m_createdFrames.append(currentFrame); + m_frameBookmarks[numOfFrames] = frameBookmark; ++numOfFrames; } @@ -299,4 +273,214 @@ void TraceLoader::addEnumSignature(unsigned id, ApiTraceEnumSignature *signature m_enumSignatures[id] = signature; } +void TraceLoader::searchNext(int startFrame, + const QString &str, + Qt::CaseSensitivity sensitivity) +{ + Q_ASSERT(m_parser.supportsOffsets()); + if (m_parser.supportsOffsets()) { + const FrameBookmark &frameBookmark = m_frameBookmarks[startFrame]; + m_parser.setBookmark(frameBookmark.start); + Trace::Call *call = 0; + while ((call = m_parser.parse_call())) { + + if (callContains(call, str, sensitivity)) { + unsigned frameIdx = callInFrame(call->no); + ApiTraceFrame *frame = m_createdFrames[frameIdx]; + const QVector calls = + fetchFrameContents(frame); + for (int i = 0; i < calls.count(); ++i) { + if (calls[i]->index() == call->no) { + emit searchResult(ApiTrace::SearchResult_Found, calls[i]); + break; + } + } + delete call; + return; + } + + delete call; + } + } + emit searchResult(ApiTrace::SearchResult_NotFound, 0); +} + +void TraceLoader::searchPrev(int startFrame, + const QString &str, + Qt::CaseSensitivity sensitivity) +{ + Q_ASSERT(m_parser.supportsOffsets()); + if (m_parser.supportsOffsets()) { + Trace::Call *call = 0; + QList frameCalls; + int frameIdx = startFrame; + + const FrameBookmark &frameBookmark = m_frameBookmarks[frameIdx]; + int numCallsToParse = frameBookmark.numberOfCalls; + m_parser.setBookmark(frameBookmark.start); + + while ((call = m_parser.parse_call())) { + + frameCalls.append(call); + --numCallsToParse; + + if (numCallsToParse == 0) { + bool foundCall = searchCallsBackwards(frameCalls, + frameIdx, + str, sensitivity); + + qDeleteAll(frameCalls); + frameCalls.clear(); + if (foundCall) { + return; + } + + --frameIdx; + + if (frameIdx >= 0) { + const FrameBookmark &frameBookmark = + m_frameBookmarks[frameIdx]; + m_parser.setBookmark(frameBookmark.start); + numCallsToParse = frameBookmark.numberOfCalls; + } + } + } + } + emit searchResult(ApiTrace::SearchResult_NotFound, 0); +} + +bool TraceLoader::searchCallsBackwards(const QList &calls, + int frameIdx, + const QString &str, + Qt::CaseSensitivity sensitivity) +{ + for (int i = calls.count() - 1; i >= 0; --i) { + Trace::Call *call = calls[i]; + if (callContains(call, str, sensitivity)) { + ApiTraceFrame *frame = m_createdFrames[frameIdx]; + const QVector apiCalls = + fetchFrameContents(frame); + for (int i = 0; i < apiCalls.count(); ++i) { + if (apiCalls[i]->index() == call->no) { + emit searchResult(ApiTrace::SearchResult_Found, apiCalls[i]); + break; + } + } + return true; + } + } + return false; +} + +int TraceLoader::callInFrame(int callIdx) const +{ + unsigned numCalls = 0; + + for (int frameIdx = 0; frameIdx <= m_frameBookmarks.size(); ++frameIdx) { + const FrameBookmark &frameBookmark = m_frameBookmarks[frameIdx]; + unsigned firstCall = numCalls; + unsigned endCall = numCalls + frameBookmark.numberOfCalls; + if (firstCall <= callIdx && endCall > callIdx) { + return frameIdx; + } + numCalls = endCall; + } + Q_ASSERT(!"call not in the trace"); + return 0; +} + +bool TraceLoader::callContains(Trace::Call *call, + const QString &str, + Qt::CaseSensitivity sensitivity) +{ + /* + * FIXME: do string comparison directly on Trace::Call + */ + ApiTraceCall *apiCall = apiCallFromTraceCall(call, m_helpHash, + 0, this); + bool result = apiCall->contains(str, sensitivity); + delete apiCall; + return result; +} + +QVector +TraceLoader::fetchFrameContents(ApiTraceFrame *currentFrame) +{ + Q_ASSERT(currentFrame); + if (m_parser.supportsOffsets()) { + unsigned frameIdx = currentFrame->number; + int numOfCalls = numberOfCallsInFrame(frameIdx); + + if (numOfCalls) { + quint64 binaryDataSize = 0; + QVector calls(numOfCalls); + const FrameBookmark &frameBookmark = m_frameBookmarks[frameIdx]; + + m_parser.setBookmark(frameBookmark.start); + + Trace::Call *call; + int parsedCalls = 0; + while ((call = m_parser.parse_call())) { + ApiTraceCall *apiCall = + apiCallFromTraceCall(call, m_helpHash, + currentFrame, this); + calls[parsedCalls] = apiCall; + Q_ASSERT(calls[parsedCalls]); + if (apiCall->hasBinaryData()) { + QByteArray data = + apiCall->arguments()[ + apiCall->binaryDataIndex()].toByteArray(); + binaryDataSize += data.size(); + } + + ++parsedCalls; + + delete call; + + if (ApiTrace::isCallAFrameMarker(apiCall, m_frameMarker)) { + break; + } + + } + assert(parsedCalls == numOfCalls); + Q_ASSERT(parsedCalls == calls.size()); + calls.squeeze(); + + Q_ASSERT(parsedCalls == currentFrame->numChildrenToLoad()); + emit frameContentsLoaded(currentFrame, + calls, binaryDataSize); + return calls; + } + } + return QVector(); +} + +void TraceLoader::findFrameStart(ApiTraceFrame *frame) +{ + loadFrame(frame); + emit foundFrameStart(frame); +} + +void TraceLoader::findFrameEnd(ApiTraceFrame *frame) +{ + loadFrame(frame); + emit foundFrameEnd(frame); +} + +void TraceLoader::findCallIndex(int index) +{ + int frameIdx = callInFrame(index); + ApiTraceFrame *frame = m_createdFrames[frameIdx]; + QVector calls = fetchFrameContents(frame); + QVector::const_iterator itr; + ApiTraceCall *call = 0; + for (itr = calls.constBegin(); itr != calls.constEnd(); ++itr) { + if ((*itr)->index() == index) { + call = *itr; + } + } + Q_ASSERT(call); + emit foundCallIndex(call); +} + #include "traceloader.moc"