Doxygen
Loading...
Searching...
No Matches
FilterCache Class Reference

Classes

struct  FilterCacheItem
 

Public Member Functions

bool getFileContents (const QCString &fileName, size_t startLine, size_t endLine, std::string &str)
 collects the part of file fileName starting at startLine and ending at endLine into buffer str.
 

Static Public Member Functions

static FilterCacheinstance ()
 

Private Types

using LineOffsets = std::vector<size_t>
 

Private Member Functions

bool getFileContentsPipe (const QCString &fileName, const QCString &filter, size_t startLine, size_t endLine, std::string &str)
 
bool getFileContentsDisk (const QCString &fileName, size_t startLine, size_t endLine, std::string &str)
 reads the fragment start at startLine and ending at endLine from file fileName into buffer str
 
void compileLineOffsets (const QCString &fileName, const std::string &str)
 computes the starting offset for each line for file fileName, whose contents should already be stored in buffer str.
 
auto getFragmentLocation (const LineOffsets &lineOffsets, size_t startLine, size_t endLine) -> std::tuple< size_t, size_t >
 Returns the byte offset and size within a file of a fragment given the array of line offsets and the start and end line of the fragment.
 
void shrinkBuffer (std::string &str, const QCString &fileName, size_t startLine, size_t endLine)
 Shrinks buffer str which should hold the contents of fileName to the fragment starting a line startLine and ending at line endLine.
 
void readFragmentFromFile (std::string &str, const QCString &fileName, size_t startOffset, size_t size=0)
 Reads the fragment start at byte offset startOffset of file fileName into buffer str.
 
 FilterCache ()
 

Private Attributes

std::unordered_map< std::string, FilterCacheItemm_cache
 
std::unordered_map< std::string, LineOffsetsm_lineOffsets
 
std::mutex m_mutex
 
size_t m_endPos
 

Detailed Description

Cache for storing the result of filtering a file

Definition at line 530 of file definition.cpp.

Member Typedef Documentation

◆ LineOffsets

using FilterCache::LineOffsets = std::vector<size_t>
private

Definition at line 538 of file definition.cpp.

Constructor & Destructor Documentation

◆ FilterCache()

FilterCache::FilterCache ( )
inlineprivate

Definition at line 722 of file definition.cpp.

722: m_endPos(0) { }
size_t m_endPos

References m_endPos.

Referenced by instance().

Member Function Documentation

◆ compileLineOffsets()

void FilterCache::compileLineOffsets ( const QCString & fileName,
const std::string & str )
inlineprivate

computes the starting offset for each line for file fileName, whose contents should already be stored in buffer str.

Definition at line 666 of file definition.cpp.

667 {
668 // line 1 (index 0) is at offset 0
669 auto it = m_lineOffsets.emplace(fileName.data(),LineOffsets{0}).first;
670 const char *p=str.data();
671 while (*p)
672 {
673 char c=0;
674 while ((c=*p)!='\n' && c!=0) p++; // search until end of the line
675 if (c!=0) p++;
676 it->second.push_back(p-str.data());
677 }
678 }
std::vector< size_t > LineOffsets
std::unordered_map< std::string, LineOffsets > m_lineOffsets
const char * data() const
Returns a pointer to the contents of the string in the form of a 0-terminated C string.
Definition qcstring.h:159

References QCString::data(), and m_lineOffsets.

Referenced by shrinkBuffer().

◆ getFileContents()

bool FilterCache::getFileContents ( const QCString & fileName,
size_t startLine,
size_t endLine,
std::string & str )
inline

collects the part of file fileName starting at startLine and ending at endLine into buffer str.

Applies filtering if FILTER_SOURCE_FILES is enabled and the file extension matches a filter. Caches file information so that subsequent extraction of blocks from the same file can be performed efficiently

Definition at line 547 of file definition.cpp.

548 {
549 bool filterSourceFiles = Config_getBool(FILTER_SOURCE_FILES);
550 QCString filter = getFileFilter(fileName,TRUE);
551 bool usePipe = !filter.isEmpty() && filterSourceFiles;
552 return usePipe ? getFileContentsPipe(fileName,filter,startLine,endLine,str)
553 : getFileContentsDisk(fileName,startLine,endLine,str);
554 }
bool getFileContentsDisk(const QCString &fileName, size_t startLine, size_t endLine, std::string &str)
reads the fragment start at startLine and ending at endLine from file fileName into buffer str
bool getFileContentsPipe(const QCString &fileName, const QCString &filter, size_t startLine, size_t endLine, std::string &str)
bool isEmpty() const
Returns TRUE iff the string is empty.
Definition qcstring.h:150
#define Config_getBool(name)
Definition config.h:33
#define TRUE
Definition qcstring.h:37
QCString getFileFilter(const QCString &name, bool isSourceCode)
Definition util.cpp:1342

References Config_getBool, getFileContentsDisk(), getFileContentsPipe(), getFileFilter(), QCString::isEmpty(), and TRUE.

Referenced by readCodeFragment().

◆ getFileContentsDisk()

bool FilterCache::getFileContentsDisk ( const QCString & fileName,
size_t startLine,
size_t endLine,
std::string & str )
inlineprivate

reads the fragment start at startLine and ending at endLine from file fileName into buffer str

Definition at line 640 of file definition.cpp.

641 {
642 std::unique_lock<std::mutex> lock(m_mutex);
643 // normal file
644 //printf("getFileContents(%s): no filter\n",qPrint(fileName));
645 auto it = m_lineOffsets.find(fileName.str());
646 if (it == m_lineOffsets.end()) // new file
647 {
648 // read file completely into str buffer
649 readFragmentFromFile(str,fileName,0);
650 // shrink buffer to [startLine..endLine] part
651 shrinkBuffer(str,fileName,startLine,endLine);
652 }
653 else // file already processed before
654 {
655 lock.unlock();
656 auto [ startLineOffset, fragmentSize] = getFragmentLocation(it->second,startLine,endLine);
657 //printf("%s: existing file [%zu-%zu] -> start=%zu size=%zu\n",
658 // qPrint(fileName),startLine,endLine,startLineOffset,fragmentSize);
659 readFragmentFromFile(str,fileName,startLineOffset,fragmentSize);
660 }
661 return true;
662 }
void shrinkBuffer(std::string &str, const QCString &fileName, size_t startLine, size_t endLine)
Shrinks buffer str which should hold the contents of fileName to the fragment starting a line startLi...
auto getFragmentLocation(const LineOffsets &lineOffsets, size_t startLine, size_t endLine) -> std::tuple< size_t, size_t >
Returns the byte offset and size within a file of a fragment given the array of line offsets and the ...
void readFragmentFromFile(std::string &str, const QCString &fileName, size_t startOffset, size_t size=0)
Reads the fragment start at byte offset startOffset of file fileName into buffer str.
std::mutex m_mutex
const std::string & str() const
Definition qcstring.h:537

References getFragmentLocation(), m_lineOffsets, m_mutex, readFragmentFromFile(), shrinkBuffer(), and QCString::str().

Referenced by getFileContents().

◆ getFileContentsPipe()

bool FilterCache::getFileContentsPipe ( const QCString & fileName,
const QCString & filter,
size_t startLine,
size_t endLine,
std::string & str )
inlineprivate

Definition at line 556 of file definition.cpp.

558 {
559 std::unique_lock<std::mutex> lock(m_mutex);
560 auto it = m_cache.find(fileName.str());
561 if (it!=m_cache.end()) // cache hit: reuse stored result
562 {
563 lock.unlock();
564 auto item = it->second;
565 //printf("getFileContents(%s): cache hit\n",qPrint(fileName));
566 // file already processed, get the results after filtering from the tmp file
567 Debug::print(Debug::FilterOutput,0,"Reusing filter result for %s from %s at offset=%lld size=%zu\n",
568 qPrint(fileName),qPrint(Doxygen::filterDBFileName),item.filePos,item.fileSize);
569
570 auto it_off = m_lineOffsets.find(fileName.str());
571 assert(it_off!=m_lineOffsets.end());
572 auto [ startLineOffset, fragmentSize] = getFragmentLocation(it_off->second,startLine,endLine);
573 //printf("%s: existing file [%zu-%zu]->[%zu-%zu] size=%zu\n",
574 // qPrint(fileName),startLine,endLine,startLineOffset,endLineOffset,fragmentSize);
576 item.filePos+startLineOffset, fragmentSize);
577 return true;
578 }
579 else // cache miss: filter active but file not previously processed
580 {
581 //printf("getFileContents(%s): cache miss\n",qPrint(fileName));
582 // filter file
583 QCString cmd=filter+" \""+fileName+"\"";
584 Debug::print(Debug::ExtCmd,0,"Executing popen(`%s`)\n",qPrint(cmd));
585 FILE *f = Portable::popen(cmd,"r");
586 if (f==nullptr)
587 {
588 // handle error
589 err("Error opening filter pipe command '%s'\n",qPrint(cmd));
590 return false;
591 }
593 FilterCacheItem item;
594 item.filePos = m_endPos;
595 if (bf==nullptr)
596 {
597 // handle error
598 err("Error opening filter database file %s\n",qPrint(Doxygen::filterDBFileName));
600 return false;
601 }
602 // append the filtered output to the database file
603 size_t size=0;
604 while (!feof(f))
605 {
606 const int blockSize = 4096;
607 char buf[blockSize];
608 size_t bytesRead = fread(buf,1,blockSize,f);
609 size_t bytesWritten = fwrite(buf,1,bytesRead,bf);
610 if (bytesRead!=bytesWritten)
611 {
612 // handle error
613 err("Failed to write to filter database %s. Wrote %zu out of %zu bytes\n",
614 qPrint(Doxygen::filterDBFileName),bytesWritten,bytesRead);
616 fclose(bf);
617 return false;
618 }
619 size+=bytesWritten;
620 str+=std::string_view(buf,bytesWritten);
621 }
622 item.fileSize = size;
623 // add location entry to the dictionary
624 m_cache.emplace(fileName.str(),item);
625 Debug::print(Debug::FilterOutput,0,"Storing new filter result for %s in %s at offset=%lld size=%zu\n",
626 qPrint(fileName),qPrint(Doxygen::filterDBFileName),item.filePos,item.fileSize);
627 // update end of file position
628 m_endPos += size;
630 fclose(bf);
631
632 // shrink buffer to [startLine..endLine] part
633 shrinkBuffer(str,fileName,startLine,endLine);
634 }
635 return true;
636 }
@ FilterOutput
Definition debug.h:37
@ ExtCmd
Definition debug.h:35
static void print(DebugMask mask, int prio, const char *fmt,...)
Definition debug.cpp:81
static QCString filterDBFileName
Definition doxygen.h:133
std::unordered_map< std::string, FilterCacheItem > m_cache
#define err(fmt,...)
Definition message.h:84
FILE * popen(const QCString &name, const QCString &type)
Definition portable.cpp:496
FILE * fopen(const QCString &fileName, const QCString &mode)
Definition portable.cpp:366
int pclose(FILE *stream)
Definition portable.cpp:505
int fclose(FILE *f)
Definition portable.cpp:386
const char * qPrint(const char *s)
Definition qcstring.h:672

References err, Debug::ExtCmd, FilterCache::FilterCacheItem::filePos, FilterCache::FilterCacheItem::fileSize, Doxygen::filterDBFileName, Debug::FilterOutput, Portable::fopen(), getFragmentLocation(), m_cache, m_endPos, m_lineOffsets, m_mutex, Portable::pclose(), Portable::popen(), Debug::print(), qPrint(), readFragmentFromFile(), shrinkBuffer(), and QCString::str().

Referenced by getFileContents().

◆ getFragmentLocation()

auto FilterCache::getFragmentLocation ( const LineOffsets & lineOffsets,
size_t startLine,
size_t endLine ) -> std::tuple<size_t,size_t>
inlineprivate

Returns the byte offset and size within a file of a fragment given the array of line offsets and the start and end line of the fragment.

Definition at line 682 of file definition.cpp.

684 {
685 assert(startLine > 0);
686 assert(startLine <= endLine);
687 const size_t startLineOffset = lineOffsets[std::min(startLine-1,lineOffsets.size()-1)];
688 const size_t endLineOffset = lineOffsets[std::min(endLine, lineOffsets.size()-1)];
689 assert(startLineOffset <= endLineOffset);
690 const size_t fragmentSize = endLineOffset-startLineOffset;
691 return std::tie(startLineOffset,fragmentSize);
692 };

Referenced by getFileContentsDisk(), getFileContentsPipe(), and shrinkBuffer().

◆ instance()

FilterCache & FilterCache::instance ( )
static

Definition at line 729 of file definition.cpp.

730{
731 static FilterCache theInstance;
732 return theInstance;
733}

References FilterCache().

Referenced by readCodeFragment().

◆ readFragmentFromFile()

void FilterCache::readFragmentFromFile ( std::string & str,
const QCString & fileName,
size_t startOffset,
size_t size = 0 )
inlineprivate

Reads the fragment start at byte offset startOffset of file fileName into buffer str.

Result will be a null terminated. If size==0 the whole file will be read and startOffset is ignored. If size>0, size bytes will be read.

Definition at line 713 of file definition.cpp.

714 {
715 std::ifstream ifs = Portable::openInputStream(fileName,true,true);
716 if (size==0) { startOffset=0; size = static_cast<size_t>(ifs.tellg()); }
717 ifs.seekg(startOffset, std::ios::beg);
718 str.resize(size);
719 ifs.read(str.data(), size);
720 }
std::ifstream openInputStream(const QCString &name, bool binary=false, bool openAtEnd=false)
Definition portable.cpp:676

References Portable::openInputStream().

Referenced by getFileContentsDisk(), and getFileContentsPipe().

◆ shrinkBuffer()

void FilterCache::shrinkBuffer ( std::string & str,
const QCString & fileName,
size_t startLine,
size_t endLine )
inlineprivate

Shrinks buffer str which should hold the contents of fileName to the fragment starting a line startLine and ending at line endLine.

Definition at line 696 of file definition.cpp.

697 {
698 // compute offsets from start for each line
699 compileLineOffsets(fileName,str);
700 auto it = m_lineOffsets.find(fileName.str());
701 assert(it!=m_lineOffsets.end());
702 const LineOffsets &lineOffsets = it->second;
703 auto [ startLineOffset, fragmentSize] = getFragmentLocation(lineOffsets,startLine,endLine);
704 //printf("%s: new file [%zu-%zu]->[%zu-%zu] size=%zu\n",
705 // qPrint(fileName),startLine,endLine,startLineOffset,endLineOffset,fragmentSize);
706 str.erase(0,startLineOffset);
707 str.resize(fragmentSize);
708 }
void compileLineOffsets(const QCString &fileName, const std::string &str)
computes the starting offset for each line for file fileName, whose contents should already be stored...

References compileLineOffsets(), getFragmentLocation(), m_lineOffsets, and QCString::str().

Referenced by getFileContentsDisk(), and getFileContentsPipe().

Member Data Documentation

◆ m_cache

std::unordered_map<std::string,FilterCacheItem> FilterCache::m_cache
private

Definition at line 723 of file definition.cpp.

Referenced by getFileContentsPipe().

◆ m_endPos

size_t FilterCache::m_endPos
private

Definition at line 726 of file definition.cpp.

Referenced by FilterCache(), and getFileContentsPipe().

◆ m_lineOffsets

std::unordered_map<std::string,LineOffsets> FilterCache::m_lineOffsets
private

◆ m_mutex

std::mutex FilterCache::m_mutex
private

Definition at line 725 of file definition.cpp.

Referenced by getFileContentsDisk(), and getFileContentsPipe().


The documentation for this class was generated from the following file: