src/versit/qversitreader_p.h
changeset 5 603d3f8b6302
parent 0 876b1a06bc25
equal deleted inserted replaced
3:e4ebb16b39ea 5:603d3f8b6302
    81 
    81 
    82 // The maximum number of bytes allowed to stay in memory after being read.  The smaller this is,
    82 // The maximum number of bytes allowed to stay in memory after being read.  The smaller this is,
    83 // the more time spent moving bytes around.  The larger it is, the more memory is wasted.
    83 // the more time spent moving bytes around.  The larger it is, the more memory is wasted.
    84 static const int MAX_OLD_BYTES_TO_KEEP = 8192;
    84 static const int MAX_OLD_BYTES_TO_KEEP = 8192;
    85 
    85 
    86 class Q_AUTOTEST_EXPORT VersitCursor
    86 /*
       
    87  * An LByteArray has a subset of QByteArray's interface, plus an efficient chopLeft function
       
    88  * 
       
    89  * It stores a QByteArray internally, plus a marker of where it starts and where it ends.
       
    90  */
       
    91 class Q_AUTOTEST_EXPORT LByteArray
    87 {
    92 {
    88 public:
    93 public:
    89     VersitCursor() : position(-1), selection(-1) {}
    94     LByteArray() : mStart(0), mEnd(0) {}
    90     explicit VersitCursor(const QByteArray& d) :data(d), position(0), selection(0) {}
    95     explicit LByteArray(const QByteArray& d) :mData(d), mStart(0), mEnd(d.size()) {}
    91     QByteArray data;
    96     bool isEmpty() const {
    92     int position;
    97         return mEnd <= mStart;
    93     int selection;
    98     }
    94 
    99     char at(int i) const {
    95     void setData(const QByteArray& d) {data = d; position = selection = 0;}
   100         return mData.at(mStart + i);
    96     void setPosition(int pos) {position = pos; selection = qMax(pos, selection);}
   101     }
    97     void setSelection(int pos) {selection = qMax(pos, position);}
   102     QByteArray toByteArray() const {
    98     void dropOldData()
   103         return mData.mid(mStart, mEnd-mStart);
    99     {
   104     }
   100         if (position > MAX_OLD_BYTES_TO_KEEP && selection >= position) {
   105     /* Removes \a n bytes from the start of the QByteArray. */ 
   101             data.remove(0, position);
   106     void chopLeft(int n) {
   102             selection -= position;
   107         Q_ASSERT(size() >= n && n >= 0);
   103             position = 0;
   108         mStart += n;
       
   109     }
       
   110     QByteArray left(int n) {
       
   111         Q_ASSERT(size() >= n && n >= 0);
       
   112         return mData.mid(mStart, n);
       
   113     }
       
   114     int indexOf(const QByteArray& needle) {
       
   115         int index = mData.indexOf(needle, mStart) - mStart;
       
   116         if (index < size())
       
   117             return index;
       
   118         return -1;
       
   119     }
       
   120     int size() const {
       
   121         return mEnd - mStart;
       
   122     }
       
   123     const char* constData() const {
       
   124         return mData.constData() + mStart;
       
   125     }
       
   126     LByteArray& operator=(const QByteArray& ba) {
       
   127         mData = ba;
       
   128         mStart = 0;
       
   129         mEnd = mData.size();
       
   130         return *this;
       
   131     }
       
   132     bool operator==(const QByteArray& ba) {
       
   133         return toByteArray() == ba;
       
   134     }
       
   135     bool operator!=(const QByteArray& ba) {
       
   136         return toByteArray() != ba;
       
   137     }
       
   138 
       
   139 private:
       
   140     /* Clears the memory of bytes before the start marker */
       
   141     void dropOldData() {
       
   142         if (mStart > MAX_OLD_BYTES_TO_KEEP && mEnd >= mStart) {
       
   143             mData.remove(0, mStart);
       
   144             mEnd -= mStart;
       
   145             mStart = 0;
   104         }
   146         }
   105     }
   147     }
       
   148     QByteArray mData;
       
   149     int mStart;
       
   150     int mEnd;
       
   151     friend class LineReader;
   106 };
   152 };
   107 
   153 
   108 class Q_AUTOTEST_EXPORT LineReader
   154 class Q_AUTOTEST_EXPORT LineReader
   109 {
   155 {
   110 public:
   156 public:
   111     LineReader(QIODevice* device, QTextCodec* codec, int chunkSize = 1000);
   157     LineReader(QIODevice* device, QTextCodec* codec, int chunkSize = 1000);
   112     VersitCursor readLine();
   158     LByteArray readLine();
       
   159     void pushLine(const QByteArray& line);
   113     int odometer();
   160     int odometer();
   114     bool atEnd();
   161     bool atEnd();
   115     QTextCodec* codec();
   162     QTextCodec* codec();
   116 
   163 
   117 private:
   164 private:
   118     bool tryReadLine(VersitCursor& cursor, bool atEnd);
   165     bool tryReadLine(LByteArray& cursor, bool atEnd);
   119 
   166 
   120     QIODevice* mDevice;
   167     QIODevice* mDevice;
   121     QTextCodec* mCodec;
   168     QTextCodec* mCodec;
   122     int mChunkSize; // How many bytes to read in one go.
   169     int mChunkSize; // How many bytes to read in one go.
   123     QList<QByteArrayMatcher> mCrlfList;
   170     QList<QByteArrayMatcher> mCrlfList;
   124     VersitCursor mBuffer;
   171     QByteArray mFirstLine; // Stores a line that has been "pushed" in front by pushLine
       
   172     LByteArray mBuffer;
   125     int mOdometer;
   173     int mOdometer;
   126     int mSearchFrom;
   174     int mSearchFrom;
   127 };
   175 };
   128 
   176 
   129 class Q_AUTOTEST_EXPORT QVersitReaderPrivate : public QThread
   177 class Q_AUTOTEST_EXPORT QVersitReaderPrivate : public QThread
   131     Q_OBJECT
   179     Q_OBJECT
   132 
   180 
   133 public: // Constructors and destructor
   181 public: // Constructors and destructor
   134     QVersitReaderPrivate();
   182     QVersitReaderPrivate();
   135     ~QVersitReaderPrivate();
   183     ~QVersitReaderPrivate();
       
   184 
       
   185     static QHash<QPair<QVersitDocument::VersitType,QString>, QVersitProperty::ValueType>*
       
   186         valueTypeMap();
   136     void init(QVersitReader* reader);
   187     void init(QVersitReader* reader);
   137 
   188 
   138 signals:
   189 signals:
   139     void stateChanged(QVersitReader::State state);
   190     void stateChanged(QVersitReader::State state);
   140     void resultsAvailable();
   191     void resultsAvailable();
   151     void setError(QVersitReader::Error);
   202     void setError(QVersitReader::Error);
   152     QVersitReader::Error error() const;
   203     QVersitReader::Error error() const;
   153     void setCanceling(bool cancelling);
   204     void setCanceling(bool cancelling);
   154     bool isCanceling();
   205     bool isCanceling();
   155 
   206 
   156     bool parseVersitDocument(LineReader& device,
   207     bool parseVersitDocument(LineReader& device, QVersitDocument& document);
   157                              QVersitDocument& document,
   208     bool parseVersitDocumentBody(LineReader& device, QVersitDocument& document);
   158                              bool foundBegin = false);
       
   159 
   209 
   160     QVersitProperty parseNextVersitProperty(
   210     QVersitProperty parseNextVersitProperty(
   161         QVersitDocument::VersitType versitType,
   211         QVersitDocument::VersitType versitType,
   162         LineReader& lineReader);
   212         LineReader& lineReader);
   163 
   213 
   164     void parseVCard21Property(
   214     void parseVCard21Property(
   165         VersitCursor& text,
   215         LByteArray& text,
   166         QVersitProperty& property,
   216         QVersitProperty& property,
   167         LineReader& lineReader);
   217         LineReader& lineReader);
   168 
   218 
   169     void parseVCard30Property(
   219     void parseVCard30Property(
   170         VersitCursor& text,
   220         QVersitDocument::VersitType versitType,
       
   221         LByteArray& text,
   171         QVersitProperty& property,
   222         QVersitProperty& property,
   172         LineReader& lineReader);
   223         LineReader& lineReader);
   173 
   224 
   174     bool setVersionFromProperty(
   225     bool setVersionFromProperty(
   175         QVersitDocument& document,
   226         QVersitDocument& document,
   176         const QVersitProperty& property) const;
   227         const QVersitProperty& property) const;
   177 
   228 
   178     bool unencode(
   229     bool unencode(
   179         QByteArray& value,
   230         QByteArray& value,
   180         VersitCursor& cursor,
       
   181         QVersitProperty& property,
   231         QVersitProperty& property,
   182         LineReader& lineReader) const;
   232         LineReader& lineReader) const;
   183 
   233 
   184     QString decodeCharset(
   234     QString decodeCharset(
   185         const QByteArray& value,
   235         const QByteArray& value,
   189 
   239 
   190     void decodeQuotedPrintable(QByteArray& text) const;
   240     void decodeQuotedPrintable(QByteArray& text) const;
   191 
   241 
   192 
   242 
   193     /* These functions operate on a cursor describing a single line */
   243     /* These functions operate on a cursor describing a single line */
   194     QPair<QStringList,QString> extractPropertyGroupsAndName(VersitCursor& line, QTextCodec* codec)
   244     QPair<QStringList,QString> extractPropertyGroupsAndName(LByteArray& line, QTextCodec* codec)
   195             const;
   245             const;
   196     QByteArray extractPropertyValue(VersitCursor& line) const;
   246     QMultiHash<QString,QString> extractVCard21PropertyParams(LByteArray& line, QTextCodec* codec)
   197     QMultiHash<QString,QString> extractVCard21PropertyParams(VersitCursor& line, QTextCodec* codec)
       
   198             const;
   247             const;
   199     QMultiHash<QString,QString> extractVCard30PropertyParams(VersitCursor& line, QTextCodec* codec)
   248     QMultiHash<QString,QString> extractVCard30PropertyParams(LByteArray& line, QTextCodec* codec)
   200             const;
   249             const;
   201 
   250 
   202     // "Private" functions
   251     // "Private" functions
   203     QList<QByteArray> extractParams(VersitCursor& line, QTextCodec *codec) const;
   252     QList<QByteArray> extractParams(LByteArray& line, QTextCodec *codec) const;
   204     QList<QByteArray> extractParts(const QByteArray& text, const QByteArray& separator,
   253     QList<QByteArray> extractParts(const QByteArray& text, const QByteArray& separator,
   205                                    QTextCodec *codec) const;
   254                                    QTextCodec *codec) const;
   206     QByteArray extractPart(const QByteArray& text, int startPosition, int length=-1) const;
   255     QByteArray extractPart(const QByteArray& text, int startPosition, int length=-1) const;
   207     QString paramName(const QByteArray& parameter, QTextCodec* codec) const;
   256     QString paramName(const QByteArray& parameter, QTextCodec* codec) const;
   208     QString paramValue(const QByteArray& parameter, QTextCodec* codec) const;
   257     QString paramValue(const QByteArray& parameter, QTextCodec* codec) const;
   209     static bool containsAt(const QByteArray& text, const QByteArray& ba, int index);
   258     template <class T> static bool containsAt(const T& text, const QByteArray& ba, int index);
   210     bool splitStructuredValue(QVersitProperty& property,
   259     bool splitStructuredValue(QVersitProperty& property,
   211                               bool hasEscapedBackslashes) const;
   260                               bool hasEscapedBackslashes) const;
   212     static QStringList splitValue(const QString& string,
   261     static QStringList splitValue(const QString& string,
   213                                   const QChar& sep,
   262                                   const QChar& sep,
   214                                   QString::SplitBehavior behaviour,
   263                                   QString::SplitBehavior behaviour,
   215                                   bool hasEscapedBackslashes);
   264                                   bool hasEscapedBackslashes);
   216     static void removeBackSlashEscaping(QString& text);
   265     static void removeBackSlashEscaping(QString& text);
   217 
   266 
   218 public: // Data
   267 // Data
   219     /* key is the document type and property name, value is the type of property it is.
   268 public:
   220        If there is no entry, assume it is a PlainType */
       
   221     QHash<QPair<QVersitDocument::VersitType,QString>, QVersitProperty::ValueType> mValueTypeMap;
       
   222     QPointer<QIODevice> mIoDevice;
   269     QPointer<QIODevice> mIoDevice;
   223     QScopedPointer<QBuffer> mInputBytes; // Holds the data set by setData()
   270     QScopedPointer<QBuffer> mInputBytes; // Holds the data set by setData()
   224     QList<QVersitDocument> mVersitDocuments;
   271     QList<QVersitDocument> mVersitDocuments;
   225     int mDocumentNestingLevel; // Depth in parsing nested Versit documents
   272     int mDocumentNestingLevel; // Depth in parsing nested Versit documents
   226     QTextCodec* mDefaultCodec;
   273     QTextCodec* mDefaultCodec;
   227     QVersitReader::State mState;
   274     QVersitReader::State mState;
   228     QVersitReader::Error mError;
   275     QVersitReader::Error mError;
   229     bool mIsCanceling;
   276     bool mIsCanceling;
   230     mutable QMutex mMutex;
   277     mutable QMutex mMutex;
       
   278 
       
   279 private:
       
   280     /* key is the document type and property name, value is the type of property it is.
       
   281        If there is no entry, assume it is a PlainType */
       
   282     static QHash<QPair<QVersitDocument::VersitType,QString>, QVersitProperty::ValueType>* mValueTypeMap;
   231 };
   283 };
   232 
   284 
   233 QTM_END_NAMESPACE
   285 QTM_END_NAMESPACE
   234 
   286 
   235 #endif // QVERSITREADER_P_H
   287 #endif // QVERSITREADER_P_H