Skip to content

Commit

Permalink
Merge pull request #4381 from dmitrio95/276235-2.X-system-staff-text-2
Browse files Browse the repository at this point in the history
fix #276235: make it possible to enable readahead for XmlReader
  • Loading branch information
anatoly-os committed Dec 12, 2018
2 parents 2d0c3a6 + 3a10013 commit 6d70cc9
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 18 deletions.
34 changes: 16 additions & 18 deletions libmscore/read206.cpp
Expand Up @@ -2949,26 +2949,24 @@ static void readMeasure(Measure* m, int staffIdx, XmlReader& e)
// MuseScore 3 has different types for system text and
// staff text while MuseScore 2 didn't.
// We need to decide first which one we should create.
QIODevice* dev = e.device();
QString styleName;
if (dev && !dev->isSequential()) { // we want to be able to seek a position
const auto pos = dev->pos();
dev->seek(e.characterOffset());
const QString closeTag = QString("</").append(tag).append(">");
QByteArray arrLine = dev->readLine();
while (!arrLine.isEmpty()) {
QString line(arrLine);
if (line.contains("<style>")) {
QRegExp re("<style>([A-z0-9]+)</style>");
if (re.indexIn(line) > -1)
styleName = re.cap(1);
break;
if (e.readAheadAvailable()) {
e.performReadAhead([&styleName, tag](QIODevice& dev) {
const QString closeTag = QString("</").append(tag).append(">");
QByteArray arrLine = dev.readLine();
while (!arrLine.isEmpty()) {
QString line(arrLine);
if (line.contains("<style>")) {
QRegExp re("<style>([A-z0-9]+)</style>");
if (re.indexIn(line) > -1)
styleName = re.cap(1);
return;
}
if (line.contains(closeTag))
return;
arrLine = dev.readLine();
}
if (line.contains(closeTag))
break;
arrLine = dev->readLine();
}
dev->seek(pos);
});
}
StaffTextBase* t;
if (styleName == "System" || styleName == "Tempo"
Expand Down
3 changes: 3 additions & 0 deletions libmscore/scorefile.cpp
Expand Up @@ -816,6 +816,8 @@ Score::FileError MasterScore::loadCompressedMsc(QIODevice* io, bool ignoreVersio
}
}
XmlReader e(dbuf);
QBuffer readAheadBuf(&dbuf);
e.setReadAheadDevice(&readAheadBuf);
e.setDocName(masterScore()->fileInfo()->completeBaseName());

FileError retval = read1(e, ignoreVersionError);
Expand Down Expand Up @@ -873,6 +875,7 @@ Score::FileError MasterScore::loadMsc(QString name, QIODevice* io, bool ignoreVe
return loadCompressedMsc(io, ignoreVersionError);
else {
XmlReader r(io);
r.setReadAheadDevice(io);
return read1(r, ignoreVersionError);
}
}
Expand Down
10 changes: 10 additions & 0 deletions libmscore/xml.h
Expand Up @@ -67,6 +67,10 @@ class LinksIndexer {
class XmlReader : public QXmlStreamReader {
QString docName; // used for error reporting

// For readahead possibility.
// If needed, must be explicitly set by setReadAheadDevice.
QIODevice* _readAheadDevice = nullptr;

// Score read context (for read optimizations):
int _tick { 0 };
int _tickOffset { 0 };
Expand Down Expand Up @@ -105,6 +109,7 @@ class XmlReader : public QXmlStreamReader {
XmlReader(QIODevice* d, const QString& st = QString()) : QXmlStreamReader(d), docName(st) {}
XmlReader(const QString& d, const QString& st = QString()) : QXmlStreamReader(d), docName(st) {}
XmlReader(const XmlReader&) = delete;
XmlReader& operator=(const XmlReader&) = delete;
~XmlReader();

bool hasAccidental; // used for userAccidental backward compatibility
Expand Down Expand Up @@ -195,6 +200,11 @@ class XmlReader : public QXmlStreamReader {
Tid addUserTextStyle(const QString& name);
Tid lookupUserTextStyle(const QString& name);

// Ownership on read ahead device is NOT transfered to XmlReader.
void setReadAheadDevice(QIODevice* dev) { if (!dev->isSequential()) _readAheadDevice = dev; }
bool readAheadAvailable() const { return bool(_readAheadDevice); }
void performReadAhead(std::function<void(QIODevice&)> readAheadRoutine);

QList<std::pair<Element*, QPointF>>& fixOffsets() { return _fixOffsets; }
};

Expand Down
21 changes: 21 additions & 0 deletions libmscore/xmlreader.cpp
Expand Up @@ -555,6 +555,27 @@ Tid XmlReader::lookupUserTextStyle(const QString& name)
return Tid::TEXT_STYLES; // not found
}

//---------------------------------------------------------
// performReadAhead
// If f is called, the device will be non-sequential and
// open. Reading position equals to the current value of
// characterOffset(), but it is possible to seek for any
// other position inside f.
//---------------------------------------------------------

void XmlReader::performReadAhead(std::function<void(QIODevice&)> f)
{
if (!_readAheadDevice || _readAheadDevice->isSequential())
return;
if (!_readAheadDevice->isOpen())
_readAheadDevice->open(QIODevice::ReadOnly);

const auto pos = _readAheadDevice->pos();
_readAheadDevice->seek(characterOffset());
f(*_readAheadDevice);
_readAheadDevice->seek(pos);
}

//---------------------------------------------------------
// addConnectorInfo
//---------------------------------------------------------
Expand Down

0 comments on commit 6d70cc9

Please sign in to comment.