]> git.cworth.org Git - apitrace/blobdiff - gui/traceloader.cpp
Fix and cleanup state lookups on frames.
[apitrace] / gui / traceloader.cpp
index a6ffd2978709a11d61c0323b9e687e34421c1520..9480f459e015505e79266843e0f2d80ae2568ffb 100644 (file)
@@ -56,49 +56,7 @@ void TraceLoader::loadTrace(const QString &filename)
 
 void TraceLoader::loadFrame(ApiTraceFrame *currentFrame)
 {
-    if (m_parser.supportsOffsets()) {
-        unsigned frameIdx = currentFrame->number;
-        int numOfCalls = numberOfCallsInFrame(frameIdx);
-
-        if (numOfCalls) {
-            quint64 binaryDataSize = 0;
-            QVector<ApiTraceCall*> 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());
-            Q_ASSERT(parsedCalls == currentFrame->numChildrenToLoad());
-            calls.squeeze();
-            currentFrame->setCalls(calls, binaryDataSize);
-            emit frameLoaded(currentFrame);
-        }
-    }
+    fetchFrameContents(currentFrame);
 }
 
 void TraceLoader::setFrameMarker(ApiTrace::FrameMarker marker)
@@ -186,8 +144,10 @@ void TraceLoader::scanTrace()
             currentFrame = new ApiTraceFrame();
             currentFrame->number = numOfFrames;
             currentFrame->setNumChildren(numOfCalls);
+            currentFrame->setLastCallIndex(call->no);
             frames.append(currentFrame);
 
+            m_createdFrames.append(currentFrame);
             m_frameBookmarks[numOfFrames] = frameBookmark;
             ++numOfFrames;
 
@@ -211,6 +171,7 @@ void TraceLoader::scanTrace()
         currentFrame->setNumChildren(numOfCalls);
         frames.append(currentFrame);
 
+        m_createdFrames.append(currentFrame);
         m_frameBookmarks[numOfFrames] = frameBookmark;
         ++numOfFrames;
     }
@@ -312,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<ApiTraceCall*> calls =
+                        fetchFrameContents(frame);
+                for (int i = 0; i < calls.count(); ++i) {
+                    if (calls[i]->index() == call->no) {
+                        emit searchResult(ApiTrace::SearchFound, calls[i]);
+                        break;
+                    }
+                }
+                delete call;
+                return;
+            }
+
+            delete call;
+        }
+    }
+    emit searchResult(ApiTrace::SearchNotFound, 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<Trace::Call*> 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::SearchNotFound, 0);
+}
+
+bool TraceLoader::searchCallsBackwards(const QList<Trace::Call*> &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<ApiTraceCall*> apiCalls =
+                    fetchFrameContents(frame);
+            for (int i = 0; i < apiCalls.count(); ++i) {
+                if (apiCalls[i]->index() == call->no) {
+                    emit searchResult(ApiTrace::SearchFound, 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<ApiTraceCall*>
+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<ApiTraceCall*> 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<ApiTraceCall*>();
+}
+
+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<ApiTraceCall*> calls = fetchFrameContents(frame);
+    QVector<ApiTraceCall*>::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"