--- a/src/versit/qversitreader_p.h Fri Sep 17 08:34:34 2010 +0300
+++ b/src/versit/qversitreader_p.h Mon Oct 04 01:37:06 2010 +0300
@@ -83,45 +83,93 @@
// the more time spent moving bytes around. The larger it is, the more memory is wasted.
static const int MAX_OLD_BYTES_TO_KEEP = 8192;
-class Q_AUTOTEST_EXPORT VersitCursor
+/*
+ * An LByteArray has a subset of QByteArray's interface, plus an efficient chopLeft function
+ *
+ * It stores a QByteArray internally, plus a marker of where it starts and where it ends.
+ */
+class Q_AUTOTEST_EXPORT LByteArray
{
public:
- VersitCursor() : position(-1), selection(-1) {}
- explicit VersitCursor(const QByteArray& d) :data(d), position(0), selection(0) {}
- QByteArray data;
- int position;
- int selection;
+ LByteArray() : mStart(0), mEnd(0) {}
+ explicit LByteArray(const QByteArray& d) :mData(d), mStart(0), mEnd(d.size()) {}
+ bool isEmpty() const {
+ return mEnd <= mStart;
+ }
+ char at(int i) const {
+ return mData.at(mStart + i);
+ }
+ QByteArray toByteArray() const {
+ return mData.mid(mStart, mEnd-mStart);
+ }
+ /* Removes \a n bytes from the start of the QByteArray. */
+ void chopLeft(int n) {
+ Q_ASSERT(size() >= n && n >= 0);
+ mStart += n;
+ }
+ QByteArray left(int n) {
+ Q_ASSERT(size() >= n && n >= 0);
+ return mData.mid(mStart, n);
+ }
+ int indexOf(const QByteArray& needle) {
+ int index = mData.indexOf(needle, mStart) - mStart;
+ if (index < size())
+ return index;
+ return -1;
+ }
+ int size() const {
+ return mEnd - mStart;
+ }
+ const char* constData() const {
+ return mData.constData() + mStart;
+ }
+ LByteArray& operator=(const QByteArray& ba) {
+ mData = ba;
+ mStart = 0;
+ mEnd = mData.size();
+ return *this;
+ }
+ bool operator==(const QByteArray& ba) {
+ return toByteArray() == ba;
+ }
+ bool operator!=(const QByteArray& ba) {
+ return toByteArray() != ba;
+ }
- void setData(const QByteArray& d) {data = d; position = selection = 0;}
- void setPosition(int pos) {position = pos; selection = qMax(pos, selection);}
- void setSelection(int pos) {selection = qMax(pos, position);}
- void dropOldData()
- {
- if (position > MAX_OLD_BYTES_TO_KEEP && selection >= position) {
- data.remove(0, position);
- selection -= position;
- position = 0;
+private:
+ /* Clears the memory of bytes before the start marker */
+ void dropOldData() {
+ if (mStart > MAX_OLD_BYTES_TO_KEEP && mEnd >= mStart) {
+ mData.remove(0, mStart);
+ mEnd -= mStart;
+ mStart = 0;
}
}
+ QByteArray mData;
+ int mStart;
+ int mEnd;
+ friend class LineReader;
};
class Q_AUTOTEST_EXPORT LineReader
{
public:
LineReader(QIODevice* device, QTextCodec* codec, int chunkSize = 1000);
- VersitCursor readLine();
+ LByteArray readLine();
+ void pushLine(const QByteArray& line);
int odometer();
bool atEnd();
QTextCodec* codec();
private:
- bool tryReadLine(VersitCursor& cursor, bool atEnd);
+ bool tryReadLine(LByteArray& cursor, bool atEnd);
QIODevice* mDevice;
QTextCodec* mCodec;
int mChunkSize; // How many bytes to read in one go.
QList<QByteArrayMatcher> mCrlfList;
- VersitCursor mBuffer;
+ QByteArray mFirstLine; // Stores a line that has been "pushed" in front by pushLine
+ LByteArray mBuffer;
int mOdometer;
int mSearchFrom;
};
@@ -133,6 +181,9 @@
public: // Constructors and destructor
QVersitReaderPrivate();
~QVersitReaderPrivate();
+
+ static QHash<QPair<QVersitDocument::VersitType,QString>, QVersitProperty::ValueType>*
+ valueTypeMap();
void init(QVersitReader* reader);
signals:
@@ -153,21 +204,21 @@
void setCanceling(bool cancelling);
bool isCanceling();
- bool parseVersitDocument(LineReader& device,
- QVersitDocument& document,
- bool foundBegin = false);
+ bool parseVersitDocument(LineReader& device, QVersitDocument& document);
+ bool parseVersitDocumentBody(LineReader& device, QVersitDocument& document);
QVersitProperty parseNextVersitProperty(
QVersitDocument::VersitType versitType,
LineReader& lineReader);
void parseVCard21Property(
- VersitCursor& text,
+ LByteArray& text,
QVersitProperty& property,
LineReader& lineReader);
void parseVCard30Property(
- VersitCursor& text,
+ QVersitDocument::VersitType versitType,
+ LByteArray& text,
QVersitProperty& property,
LineReader& lineReader);
@@ -177,7 +228,6 @@
bool unencode(
QByteArray& value,
- VersitCursor& cursor,
QVersitProperty& property,
LineReader& lineReader) const;
@@ -191,22 +241,21 @@
/* These functions operate on a cursor describing a single line */
- QPair<QStringList,QString> extractPropertyGroupsAndName(VersitCursor& line, QTextCodec* codec)
+ QPair<QStringList,QString> extractPropertyGroupsAndName(LByteArray& line, QTextCodec* codec)
const;
- QByteArray extractPropertyValue(VersitCursor& line) const;
- QMultiHash<QString,QString> extractVCard21PropertyParams(VersitCursor& line, QTextCodec* codec)
+ QMultiHash<QString,QString> extractVCard21PropertyParams(LByteArray& line, QTextCodec* codec)
const;
- QMultiHash<QString,QString> extractVCard30PropertyParams(VersitCursor& line, QTextCodec* codec)
+ QMultiHash<QString,QString> extractVCard30PropertyParams(LByteArray& line, QTextCodec* codec)
const;
// "Private" functions
- QList<QByteArray> extractParams(VersitCursor& line, QTextCodec *codec) const;
+ QList<QByteArray> extractParams(LByteArray& line, QTextCodec *codec) const;
QList<QByteArray> extractParts(const QByteArray& text, const QByteArray& separator,
QTextCodec *codec) const;
QByteArray extractPart(const QByteArray& text, int startPosition, int length=-1) const;
QString paramName(const QByteArray& parameter, QTextCodec* codec) const;
QString paramValue(const QByteArray& parameter, QTextCodec* codec) const;
- static bool containsAt(const QByteArray& text, const QByteArray& ba, int index);
+ template <class T> static bool containsAt(const T& text, const QByteArray& ba, int index);
bool splitStructuredValue(QVersitProperty& property,
bool hasEscapedBackslashes) const;
static QStringList splitValue(const QString& string,
@@ -215,10 +264,8 @@
bool hasEscapedBackslashes);
static void removeBackSlashEscaping(QString& text);
-public: // Data
- /* key is the document type and property name, value is the type of property it is.
- If there is no entry, assume it is a PlainType */
- QHash<QPair<QVersitDocument::VersitType,QString>, QVersitProperty::ValueType> mValueTypeMap;
+// Data
+public:
QPointer<QIODevice> mIoDevice;
QScopedPointer<QBuffer> mInputBytes; // Holds the data set by setData()
QList<QVersitDocument> mVersitDocuments;
@@ -228,6 +275,11 @@
QVersitReader::Error mError;
bool mIsCanceling;
mutable QMutex mMutex;
+
+private:
+ /* key is the document type and property name, value is the type of property it is.
+ If there is no entry, assume it is a PlainType */
+ static QHash<QPair<QVersitDocument::VersitType,QString>, QVersitProperty::ValueType>* mValueTypeMap;
};
QTM_END_NAMESPACE