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

Classes

struct  FilterCacheItem

Public Member Functions

bool getFileContents (const DString &fileName, size_t startLine, size_t endLine, std::string &str)

Static Public Member Functions

static FilterCacheinstance ()

Private Types

using LineOffsets = std::vector<size_t>

Private Member Functions

bool getFileContentsPipe (const DString &fileName, const DString &filter, size_t startLine, size_t endLine, std::string &str)
bool getFileContentsDisk (const DString &fileName, size_t startLine, size_t endLine, std::string &str)
void compileLineOffsets (const DString &fileName, const std::string &str)
auto getFragmentLocation (const LineOffsets &lineOffsets, size_t startLine, size_t endLine) -> std::tuple< size_t, size_t >
void shrinkBuffer (std::string &str, const DString &fileName, size_t startLine, size_t endLine)
void readFragmentFromFile (std::string &str, const DString &fileName, size_t startOffset, size_t size=0)
 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 541 of file definition.cpp.

Member Typedef Documentation

◆ LineOffsets

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

Definition at line 549 of file definition.cpp.

Constructor & Destructor Documentation

◆ FilterCache()

FilterCache::FilterCache ( )
inlineprivate

Definition at line 733 of file definition.cpp.

733: m_endPos(0) { }
size_t m_endPos

References m_endPos.

Referenced by instance().

Member Function Documentation

◆ compileLineOffsets()

void FilterCache::compileLineOffsets ( const DString & 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 677 of file definition.cpp.

678 {
679 // line 1 (index 0) is at offset 0
680 auto it = m_lineOffsets.emplace(fileName.data(),LineOffsets{0}).first;
681 const char *p=str.data();
682 while (*p)
683 {
684 char c=0;
685 while ((c=*p)!='\n' && c!=0) p++; // search until end of the line
686 if (c!=0) p++;
687 it->second.push_back(p-str.data());
688 }
689 }
const char * data() const
Returns a pointer to the contents of the string in the form of a 0-terminated C string.
Definition dstring.h:157
std::vector< size_t > LineOffsets
std::unordered_map< std::string, LineOffsets > m_lineOffsets

References DString::data(), and m_lineOffsets.

Referenced by shrinkBuffer().

◆ getFileContents()

bool FilterCache::getFileContents ( const DString & 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 558 of file definition.cpp.

559 {
560 bool filterSourceFiles = Config_getBool(FILTER_SOURCE_FILES);
561 DString filter = getFileFilter(fileName,true);
562 bool usePipe = !filter.empty() && filterSourceFiles;
563 return usePipe ? getFileContentsPipe(fileName,filter,startLine,endLine,str)
564 : getFileContentsDisk(fileName,startLine,endLine,str);
565 }
bool empty() const
Returns true iff the string is empty (std::string compatible alias for isEmpty()).
Definition dstring.h:148
bool getFileContentsPipe(const DString &fileName, const DString &filter, size_t startLine, size_t endLine, std::string &str)
bool getFileContentsDisk(const DString &fileName, size_t startLine, size_t endLine, std::string &str)
#define Config_getBool(name)
Definition config.h:33
DString getFileFilter(const DString &name, bool isSourceCode)
Definition util.cpp:1020

References Config_getBool, DString::empty(), getFileContentsDisk(), getFileContentsPipe(), and getFileFilter().

Referenced by readCodeFragment().

◆ getFileContentsDisk()

bool FilterCache::getFileContentsDisk ( const DString & 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 651 of file definition.cpp.

652 {
653 std::unique_lock<std::mutex> lock(m_mutex);
654 // normal file
655 //printf("getFileContents(%s): no filter\n",qPrint(fileName));
656 auto it = m_lineOffsets.find(fileName.str());
657 if (it == m_lineOffsets.end()) // new file
658 {
659 // read file completely into str buffer
660 readFragmentFromFile(str,fileName,0);
661 // shrink buffer to [startLine..endLine] part
662 shrinkBuffer(str,fileName,startLine,endLine);
663 }
664 else // file already processed before
665 {
666 lock.unlock();
667 auto [ startLineOffset, fragmentSize] = getFragmentLocation(it->second,startLine,endLine);
668 //printf("%s: existing file [%zu-%zu] -> start=%zu size=%zu\n",
669 // qPrint(fileName),startLine,endLine,startLineOffset,fragmentSize);
670 readFragmentFromFile(str,fileName,startLineOffset,fragmentSize);
671 }
672 return true;
673 }
const std::string & str() const
Definition dstring.h:645
void shrinkBuffer(std::string &str, const DString &fileName, size_t startLine, size_t endLine)
auto getFragmentLocation(const LineOffsets &lineOffsets, size_t startLine, size_t endLine) -> std::tuple< size_t, size_t >
void readFragmentFromFile(std::string &str, const DString &fileName, size_t startOffset, size_t size=0)
std::mutex m_mutex

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

Referenced by getFileContents().

◆ getFileContentsPipe()

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

Definition at line 567 of file definition.cpp.

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

References ASSERT, 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(), readFragmentFromFile(), shrinkBuffer(), and DString::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 693 of file definition.cpp.

695 {
696 ASSERT(startLine > 0);
697 ASSERT(startLine <= endLine);
698 const size_t startLineOffset = lineOffsets[std::min(startLine-1,lineOffsets.size()-1)];
699 const size_t endLineOffset = lineOffsets[std::min(endLine, lineOffsets.size()-1)];
700 ASSERT(startLineOffset <= endLineOffset);
701 const size_t fragmentSize = endLineOffset-startLineOffset;
702 return std::tie(startLineOffset,fragmentSize);
703 }

References ASSERT.

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

◆ instance()

FilterCache & FilterCache::instance ( )
static

Definition at line 740 of file definition.cpp.

741{
742 static FilterCache theInstance;
743 return theInstance;
744}

References FilterCache().

Referenced by readCodeFragment().

◆ readFragmentFromFile()

void FilterCache::readFragmentFromFile ( std::string & str,
const DString & 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 724 of file definition.cpp.

725 {
726 std::ifstream ifs = Portable::openInputStream(fileName,true,true);
727 if (size==0) { startOffset=0; size = static_cast<size_t>(ifs.tellg()); }
728 ifs.seekg(startOffset, std::ios::beg);
729 str.resize(size);
730 ifs.read(str.data(), size);
731 }
std::ifstream openInputStream(const DString &name, bool binary=false, bool openAtEnd=false)
Definition portable.cpp:692

References Portable::openInputStream().

Referenced by getFileContentsDisk(), and getFileContentsPipe().

◆ shrinkBuffer()

void FilterCache::shrinkBuffer ( std::string & str,
const DString & 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 707 of file definition.cpp.

708 {
709 // compute offsets from start for each line
710 compileLineOffsets(fileName,str);
711 auto it = m_lineOffsets.find(fileName.str());
712 ASSERT(it!=m_lineOffsets.end());
713 const LineOffsets &lineOffsets = it->second;
714 auto [ startLineOffset, fragmentSize] = getFragmentLocation(lineOffsets,startLine,endLine);
715 //printf("%s: new file [%zu-%zu]->[%zu-%zu] size=%zu\n",
716 // qPrint(fileName),startLine,endLine,startLineOffset,endLineOffset,fragmentSize);
717 str.erase(0,startLineOffset);
718 str.resize(fragmentSize);
719 }
void compileLineOffsets(const DString &fileName, const std::string &str)

References ASSERT, compileLineOffsets(), getFragmentLocation(), m_lineOffsets, and DString::str().

Referenced by getFileContentsDisk(), and getFileContentsPipe().

Member Data Documentation

◆ m_cache

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

Definition at line 734 of file definition.cpp.

Referenced by getFileContentsPipe().

◆ m_endPos

size_t FilterCache::m_endPos
private

Definition at line 737 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 736 of file definition.cpp.

Referenced by getFileContentsDisk(), and getFileContentsPipe().


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