File indexing completed on 2024-04-14 04:31:19

0001 /* This file is part of KDevelop
0002    Copyright 2011 Mathieu Lornac <mathieu.lornac@gmail.com>
0003    Copyright 2011 Damien Coppel <damien.coppel@gmail.com>
0004    Copyright 2011 Lionel Duc <lionel.data@gmail.com>
0005    Copyright 2011 Lucas Sarie <lucas.sarie@gmail.com>
0006    Copyright 2016 Anton Anikin <anton@anikin.xyz>
0007 
0008    This program is free software; you can redistribute it and/or
0009    modify it under the terms of the GNU General Public
0010    License as published by the Free Software Foundation; either
0011    version 2 of the License, or (at your option) any later version.
0012 
0013    This program is distributed in the hope that it will be useful,
0014    but WITHOUT ANY WARRANTY; without even the implied warranty of
0015    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0016    General Public License for more details.
0017 
0018    You should have received a copy of the GNU General Public License
0019    along with this program; see the file COPYING.  If not, write to
0020    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0021    Boston, MA 02110-1301, USA.
0022 */
0023 
0024 #include "cachegrind_parser.h"
0025 
0026 #include "debug.h"
0027 #include "cachegrind_model.h"
0028 
0029 #include <QBuffer>
0030 #include <QUrl>
0031 
0032 namespace Valgrind
0033 {
0034 
0035 CachegrindFunction* cachegrindParseCachegrindItem(const QString& line, QStringList& eventsList)
0036 {
0037     auto item = new CachegrindFunction;
0038 
0039     QStringList lineEventList = line.split(QChar(' '), QString::SkipEmptyParts);
0040     Q_ASSERT(lineEventList.size() >= eventsList.size());
0041 
0042     for (int i = 0; i < eventsList.size(); ++i) {
0043         item->eventValues += lineEventList.takeFirst().remove(QLatin1Char(',')).toInt();
0044     }
0045 
0046     QString fileCall = lineEventList.join(QChar(' '));
0047     int colonPosition = fileCall.indexOf(QChar(':'));
0048     if (colonPosition >= 0) {
0049         // file name
0050         auto fileUrl = QUrl::fromLocalFile(fileCall.mid(0, colonPosition)).adjusted(QUrl::NormalizePathSegments);
0051         item->fileNames += fileUrl.toLocalFile();
0052 
0053         // call name
0054         item->functionName = fileCall.mid(colonPosition + 1);
0055     }
0056 
0057     return item;
0058 }
0059 
0060 enum CachegrindParserState
0061 {
0062     ParseRoot,
0063     ParseProgramTotalHeader,
0064     ParseProgramTotal,
0065     ParseProgramHeader,
0066     ParseProgram
0067 };
0068 
0069 void cachegrindParse(QByteArray& baData, CachegrindFunctionsModel* model)
0070 {
0071     Q_ASSERT(model);
0072 
0073     CachegrindParserState parserState = ParseRoot;
0074     QStringList eventsList;
0075     QString eventsString;
0076     QString line;
0077 
0078     QBuffer data(&baData);
0079     data.open(QIODevice::ReadOnly);
0080 
0081     while (!data.atEnd())
0082     {
0083         // remove useless characters
0084         line = data.readLine().simplified();
0085 
0086         if (parserState == ParseRoot) {
0087             if (line.startsWith(QLatin1String("Events shown:"))) {
0088                 // 13 is 'Events shown:' length
0089                 eventsString = line.mid(13).simplified();
0090                 eventsList = eventsString.split(QChar(' '), QString::SkipEmptyParts);
0091                 parserState = ParseProgramTotalHeader;
0092             }
0093         }
0094 
0095         else if (parserState == ParseProgramTotalHeader) {
0096             if (line == eventsString) {
0097                 parserState = ParseProgramTotal;
0098             }
0099         }
0100 
0101         else if (parserState == ParseProgramHeader) {
0102             if (line.startsWith(eventsString)) {
0103                 parserState = ParseProgram;
0104             }
0105         }
0106 
0107         else if (!line.isEmpty() && line.at(0).isDigit()) {
0108             bool isTotal = (parserState == ParseProgramTotal);
0109             model->addItem(cachegrindParseCachegrindItem(line, eventsList), isTotal);
0110             if (isTotal) {
0111                 parserState = ParseProgramHeader;
0112             }
0113         }
0114     }
0115 
0116     model->setEventsList(eventsList);
0117 }
0118 
0119 }