@@ -638,23 +638,6 @@ std::string ErrorMessage::toXML() const
638638 return printer.CStr ();
639639}
640640
641- // TODO: read info from some shared resource instead?
642- static std::string readCode (const std::string &file, int linenr, int column, const char endl[])
643- {
644- std::ifstream fin (file);
645- std::string line;
646- while (linenr > 0 && std::getline (fin,line)) {
647- linenr--;
648- }
649- const std::string::size_type endPos = line.find_last_not_of (" \r\n\t " );
650- if (endPos + 1 < line.size ())
651- line.erase (endPos + 1 );
652- std::string::size_type pos = 0 ;
653- while ((pos = line.find (' \t ' , pos)) != std::string::npos)
654- line[pos] = ' ' ;
655- return line + endl + std::string ((column>0 ? column-1 : 0 ), ' ' ) + ' ^' ;
656- }
657-
658641static void replaceSpecialChars (std::string& source)
659642{
660643 // Support a few special characters to allow to specific formatting, see http://sourceforge.net/apps/phpbb/cppcheck/viewtopic.php?f=4&t=494&sid=21715d362c0dbafd3791da4d9522f814
@@ -729,7 +712,38 @@ static void replaceColors(std::string& source, bool erase) {
729712 replace (source, substitutionMapErase);
730713}
731714
732- std::string ErrorMessage::toString (bool verbose, const std::string &templateFormat, const std::string &templateLocation, bool noCode) const
715+ static std::string formatLine (std::string line, int column, const char endl[])
716+ {
717+ const std::string::size_type endPos = line.find_last_not_of (" \r\n\t " );
718+ if (endPos + 1 < line.size ())
719+ line.erase (endPos + 1 );
720+
721+ std::string::size_type pos = 0 ;
722+ while ((pos = line.find (' \t ' , pos)) != std::string::npos)
723+ line[pos] = ' ' ;
724+
725+ return line + endl + std::string ((column>0 ? column-1 : 0 ), ' ' ) + ' ^' ;
726+ }
727+
728+ std::string ErrorMessage::directSourceLineCallback (const std::string &file,
729+ int linenr,
730+ int column,
731+ const char endl[],
732+ int cachePrio)
733+ {
734+ std::ifstream fin (file);
735+ std::string line;
736+
737+ while (linenr > 0 && std::getline (fin, line))
738+ --linenr;
739+
740+ return formatLine (line, column, endl);
741+ }
742+
743+ std::string ErrorMessage::toString (bool verbose,
744+ const std::string &templateFormat,
745+ const std::string &templateLocation,
746+ SourceLineCallback sourceLineCallback) const
733747{
734748 assert (!templateFormat.empty ());
735749
@@ -770,7 +784,12 @@ std::string ErrorMessage::toString(bool verbose, const std::string &templateForm
770784 endl = " \r\n " ;
771785 else
772786 endl = " \r " ;
773- const std::string code = noCode ? " " : readCode (callStack.back ().getOrigFile (), callStack.back ().line , callStack.back ().column , endl);
787+ const std::string code = sourceLineCallback == nullptr ?
788+ " " : sourceLineCallback (callStack.back ().getOrigFile (),
789+ callStack.back ().line ,
790+ callStack.back ().column ,
791+ endl,
792+ 0 );
774793 findAndReplace (result, " {code}" , code);
775794 }
776795 } else {
@@ -785,6 +804,7 @@ std::string ErrorMessage::toString(bool verbose, const std::string &templateForm
785804 replace (result, callStackSubstitutionMap);
786805 }
787806
807+ int cachePrio = -1 ;
788808 if (!templateLocation.empty () && callStack.size () >= 2U ) {
789809 for (const FileLocation &fileLocation : callStack) {
790810 std::string text = templateLocation;
@@ -802,7 +822,12 @@ std::string ErrorMessage::toString(bool verbose, const std::string &templateForm
802822 endl = " \r\n " ;
803823 else
804824 endl = " \r " ;
805- const std::string code = noCode ? " " : readCode (fileLocation.getOrigFile (), fileLocation.line , fileLocation.column , endl);
825+ const std::string code = sourceLineCallback == nullptr ?
826+ " " : sourceLineCallback (fileLocation.getOrigFile (),
827+ fileLocation.line ,
828+ fileLocation.column ,
829+ endl,
830+ cachePrio--);
806831 findAndReplace (text, " {code}" , code);
807832 }
808833 result += ' \n ' + text;
@@ -1261,3 +1286,71 @@ std::map<std::string, std::string> createGuidelineMapping(ReportType reportType)
12611286
12621287 return guidelineMapping;
12631288}
1289+
1290+ ErrorLogger::SourceCacheEntry::SourceCacheEntry (const std::string &file, int prio)
1291+ : prio(prio)
1292+ , file(file)
1293+ , stream(std::ifstream(file))
1294+ {
1295+ }
1296+
1297+ std::string ErrorLogger::sourceLineCallback (const std::string &file,
1298+ int linenr,
1299+ int column,
1300+ const char endl[],
1301+ int cachePrio)
1302+ {
1303+ // For sorting cache entries by priority
1304+ const auto heapCompare = [](const std::shared_ptr<SourceCacheEntry> &lhs, const std::shared_ptr<SourceCacheEntry> &rhs) {
1305+ return lhs->prio > rhs->prio ;
1306+ };
1307+
1308+ std::shared_ptr<SourceCacheEntry> entry = nullptr ;
1309+
1310+ const auto existing = std::find_if (
1311+ mSourceCache .begin (),
1312+ mSourceCache .end (),
1313+ [&] (const std::shared_ptr<SourceCacheEntry> &e) { return e->file == file; }
1314+ );
1315+
1316+ if (existing == mSourceCache .end ()) {
1317+ if (mSourceCache .size () == mSourceCacheSize ) {
1318+ // Evict the cache entry with lowest priority
1319+ std::pop_heap (mSourceCache .begin (), mSourceCache .end (), heapCompare);
1320+ mSourceCache .pop_back ();
1321+ }
1322+
1323+ // Insert new entry
1324+ entry = std::make_shared<SourceCacheEntry>(file, cachePrio);
1325+ mSourceCache .push_back (entry);
1326+ std::push_heap (mSourceCache .begin (), mSourceCache .end (), heapCompare);
1327+ } else {
1328+ entry = *existing;
1329+ if (entry->prio < cachePrio) {
1330+ // Update priority and sort cache
1331+ entry->prio = cachePrio;
1332+ std::make_heap (mSourceCache .begin (), mSourceCache .end (), heapCompare);
1333+ }
1334+ }
1335+
1336+ entry->stream .clear ();
1337+ entry->stream .seekg (0 );
1338+
1339+ std::string line;
1340+ while (linenr > 0 && std::getline (entry->stream , line))
1341+ linenr--;
1342+
1343+ return formatLine (line, column, endl);
1344+ }
1345+
1346+ ErrorMessage::SourceLineCallback ErrorLogger::getSourceLineCallback ()
1347+ {
1348+ return [this ](const std::string &file,
1349+ int linenr,
1350+ int column,
1351+ const char endl[],
1352+ int cachePrio)
1353+ {
1354+ return sourceLineCallback (file, linenr, column, endl, cachePrio);
1355+ };
1356+ }
0 commit comments