Commit a0eceb5e authored by Robert Knight's avatar Robert Knight

Use a shared buffer between all filters in a chain. Should improve efficiency...

Use a shared buffer between all filters in a chain.  Should improve efficiency by reducing memory allocations.  More to the point it prevents accidental deep copying of strings which can happen if not careful with QStrings.  Most of the processing time is taken up by the regular expression parsing itself.

svn path=/branches/work/konsole-split-view/; revision=658652
parent b05880cd
......@@ -69,17 +69,17 @@ void FilterChain::reset()
while (iter.hasNext())
iter.next()->reset();
}
void FilterChain::process()
void FilterChain::setBuffer(const QString* buffer , const QList<int>* linePositions)
{
QListIterator<Filter*> iter(*this);
while (iter.hasNext())
iter.next()->process();
iter.next()->setBuffer(buffer,linePositions);
}
void FilterChain::addLine(const QString& line)
void FilterChain::process()
{
QListIterator<Filter*> iter(*this);
while (iter.hasNext())
iter.next()->addLine(line);
iter.next()->process();
}
void FilterChain::clear()
{
......@@ -114,24 +114,55 @@ QList<Filter::HotSpot*> FilterChain::hotSpots() const
}
//QList<Filter::HotSpot*> FilterChain::hotSpotsAtLine(int line) const;
void TerminalImageFilterChain::addImage(const Character* const image , int lines , int columns)
TerminalImageFilterChain::TerminalImageFilterChain()
: _buffer(0)
, _linePositions(0)
{
}
TerminalImageFilterChain::~TerminalImageFilterChain()
{
delete _buffer;
delete _linePositions;
}
void TerminalImageFilterChain::setImage(const Character* const image , int lines , int columns)
{
if (empty())
return;
// reset all filters and hotspots
reset();
PlainTextDecoder decoder;
decoder.setTrailingWhitespace(false);
QString line;
QTextStream lineStream(&line);
// setup new shared buffers for the filters to process on
QString* newBuffer = new QString();
QList<int>* newLinePositions = new QList<int>();
setBuffer( newBuffer , newLinePositions );
// free the old buffers
delete _buffer;
delete _linePositions;
_buffer = newBuffer;
_linePositions = newLinePositions;
QTextStream lineStream(_buffer);
for (int i=0 ; i < lines ; i++)
{
_linePositions->append(_buffer->length());
decoder.decodeLine(image + i*columns,columns,LINE_DEFAULT,&lineStream);
addLine(line);
line.clear();
}
}
Filter::Filter() :
_linePositions(0),
_buffer(0)
{
}
Filter::~Filter()
{
QListIterator<HotSpot*> iter(_hotspotList);
......@@ -144,42 +175,50 @@ void Filter::reset()
{
_hotspots.clear();
_hotspotList.clear();
_linePositions.clear();
_buffer.clear();
}
void Filter::setBuffer(const QString* buffer , const QList<int>* linePositions)
{
_buffer = buffer;
_linePositions = linePositions;
}
void Filter::getLineColumn(int position , int& startLine , int& startColumn)
{
for (int i = 0 ; i < _linePositions.count() ; i++)
Q_ASSERT( _linePositions );
Q_ASSERT( _buffer );
for (int i = 0 ; i < _linePositions->count() ; i++)
{
//qDebug() << "line position at " << i << " = " << _linePositions[i];
int nextLine = 0;
if ( i == _linePositions.count()-1 )
if ( i == _linePositions->count()-1 )
{
nextLine = _buffer.length();
nextLine = _buffer->length();
}
else
{
nextLine = _linePositions[i+1];
nextLine = _linePositions->value(i+1);
}
if ( _linePositions[i] <= position && position < nextLine )
if ( _linePositions->value(i) <= position && position < nextLine )
{
startLine = i;
startColumn = position - _linePositions[i];
startColumn = position - _linePositions->value(i);
return;
}
}
}
void Filter::addLine(const QString& text)
/*void Filter::addLine(const QString& text)
{
_linePositions << _buffer.length();
_buffer.append(text);
}
QString& Filter::buffer()
}*/
const QString* Filter::buffer()
{
return _buffer;
}
......@@ -302,7 +341,9 @@ QRegExp RegExpFilter::regExp() const
void RegExpFilter::process()
{
int pos = 0;
QString& text = buffer();
const QString* text = buffer();
Q_ASSERT( text );
// empty regexp does not match
if ( _searchText.isEmpty() )
......@@ -310,7 +351,7 @@ void RegExpFilter::process()
while(pos >= 0)
{
pos = _searchText.indexIn(text,pos);
pos = _searchText.indexIn(*text,pos);
if ( pos >= 0 )
{
......
......@@ -134,6 +134,8 @@ public:
};
/** Constructs a new filter. */
Filter();
virtual ~Filter();
/** Causes the filter to process the block of text currently in its internal buffer */
......@@ -146,7 +148,7 @@ public:
void reset();
/** Adds a new line of text to the filter and increments the line count */
void addLine(const QString& string);
//void addLine(const QString& string);
/** Returns the hotspot which covers the given @p line and @p column, or 0 if no hotspot covers that area */
HotSpot* hotSpotAt(int line , int column) const;
......@@ -157,19 +159,25 @@ public:
/** Returns the list of hotspots identified by the filter which occur on a given line */
QList<HotSpot*> hotSpotsAtLine(int line) const;
/**
* TODO: Document me
*/
void setBuffer(const QString* buffer , const QList<int>* linePositions);
protected:
/** Adds a new hotspot to the list */
void addHotSpot(HotSpot*);
/** Returns the internal buffer */
QString& buffer();
const QString* buffer();
/** Converts a character position within buffer() to a line and column */
void getLineColumn(int position , int& startLine , int& startColumn);
private:
QMultiHash<int,HotSpot*> _hotspots;
QList<HotSpot*> _hotspotList;
QList<int> _linePositions;
QString _buffer;
const QList<int>* _linePositions;
const QString* _buffer;
};
/**
......@@ -315,17 +323,14 @@ public:
/** Resets each filter in the chain */
void reset();
/**
* Adds a new line of text to each filter in the chain
* TODO: This is inefficient memory-wise because a new line is added for each filter.
* Only one buffer should be used for the entire chain.
*/
void addLine(const QString& line);
/**
* Processes each filter in the chain
*/
void process();
/** Sets the buffer for each filter in the chain to process. */
void setBuffer(const QString* buffer , const QList<int>* linePositions);
/** Returns the first hotspot which occurs at @p line, @p column or 0 if no hotspot was found */
Filter::HotSpot* hotSpotAt(int line , int column) const;
/** Returns a list of all the hotspots in all the chain's filters */
......@@ -339,6 +344,9 @@ public:
class TerminalImageFilterChain : public FilterChain
{
public:
TerminalImageFilterChain();
virtual ~TerminalImageFilterChain();
/**
* Set the current terminal image to @p image.
*
......@@ -346,8 +354,12 @@ public:
* @param lines The number of lines in the terminal image
* @param columns The number of columns in the terminal image
*/
void addImage(const Character* const image , int lines , int columns);
void setImage(const Character* const image , int lines , int columns);
private:
QString* _buffer;
QList<int>* _linePositions;
};
}
};
#endif //FILTER_H
......@@ -993,9 +993,16 @@ void TerminalDisplay::scrollImage(int _lines)
void TerminalDisplay::processFilters()
{
_filterChain->reset();
_filterChain->addImage(_image,_lines,_columns);
QTime t;
t.start();
_filterChain->setImage(_image,_lines,_columns);
qDebug() << "Setup filters in" << t.elapsed() << "ms.";
_filterChain->process();
qDebug() << "Processed filters in" << t.elapsed() << "ms.";
}
void TerminalDisplay::updateImage()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment