src/corelib/io/qiodevice_p.h
changeset 19 fcece45ef507
parent 18 2f34d5167611
child 33 3e2da88830cd
--- a/src/corelib/io/qiodevice_p.h	Fri Apr 16 15:50:13 2010 +0300
+++ b/src/corelib/io/qiodevice_p.h	Mon May 03 13:17:34 2010 +0300
@@ -64,6 +64,126 @@
 
 QT_BEGIN_NAMESPACE
 
+#ifndef QIODEVICE_BUFFERSIZE
+#define QIODEVICE_BUFFERSIZE Q_INT64_C(16384)
+#endif
+
+// This is QIODevice's read buffer, optimised for read(), isEmpty() and getChar()
+class QIODevicePrivateLinearBuffer
+{
+public:
+    QIODevicePrivateLinearBuffer(int) : len(0), first(0), buf(0), capacity(0) {
+    }
+    ~QIODevicePrivateLinearBuffer() {
+        delete [] buf;
+    }
+    void clear() {
+        first = buf;
+        len = 0;
+    }
+    int size() const {
+        return len;
+    }
+    bool isEmpty() const {
+        return len == 0;
+    }
+    void skip(int n) {
+        if (n >= len) {
+            clear();
+        } else {
+            len -= n;
+            first += n;
+        }
+    }
+    int getChar() {
+        if (len == 0)
+            return -1;
+        int ch = uchar(*first);
+        len--;
+        first++;
+        return ch;
+    }
+    int read(char* target, int size) {
+        int r = qMin(size, len);
+        memcpy(target, first, r);
+        len -= r;
+        first += r;
+        return r;
+    }
+    char* reserve(int size) {
+        makeSpace(size + len, freeSpaceAtEnd);
+        char* writePtr = first + len;
+        len += size;
+        return writePtr;
+    }
+    void chop(int size) {
+        if (size >= len) {
+            clear();
+        } else {
+            len -= size;
+        }
+    }
+    QByteArray readAll() {
+        char* f = first;
+        int l = len;
+        clear();
+        return QByteArray(f, l);
+    }
+    int readLine(char* target, int size) {
+        int r = qMin(size, len);
+        char* eol = static_cast<char*>(memchr(first, '\n', r));
+        if (eol)
+            r = 1+(eol-first);
+        memcpy(target, first, r);
+        len -= r;
+        first += r;
+        return int(r);
+        }
+    bool canReadLine() const {
+        return memchr(first, '\n', len);
+    }
+    void ungetChar(char c) {
+        if (first == buf) {
+            // underflow, the existing valid data needs to move to the end of the (potentially bigger) buffer
+            makeSpace(len+1, freeSpaceAtStart);
+        }
+        first--;
+        len++;
+        *first = c;
+    }
+
+private:
+    enum FreeSpacePos {freeSpaceAtStart, freeSpaceAtEnd};
+    void makeSpace(size_t required, FreeSpacePos where) {
+        size_t newCapacity = qMax(capacity, size_t(QIODEVICE_BUFFERSIZE));
+        while (newCapacity < required)
+            newCapacity *= 2;
+        int moveOffset = (where == freeSpaceAtEnd) ? 0 : newCapacity - len;
+        if (newCapacity > capacity) {
+            // allocate more space
+            char* newBuf = new char[newCapacity];
+            memmove(newBuf + moveOffset, first, len);
+            delete [] buf;
+            buf = newBuf;
+            capacity = newCapacity;
+        } else {
+            // shift any existing data to make space
+            memmove(buf + moveOffset, first, len);
+        }
+        first = buf + moveOffset;
+    }
+
+private:
+    // length of the unread data
+    int len;
+    // start of the unread data
+    char* first;
+    // the allocated buffer
+    char* buf;
+    // allocated buffer size
+    size_t capacity;
+};
+
 class Q_CORE_EXPORT QIODevicePrivate
 #ifndef QT_NO_QOBJECT
     : public QObjectPrivate
@@ -78,10 +198,15 @@
     QIODevice::OpenMode openMode;
     QString errorString;
 
-    QRingBuffer buffer;
+    QIODevicePrivateLinearBuffer buffer;
     qint64 pos;
     qint64 devicePos;
+    // these three are for fast position updates during read, avoiding isSequential test
+    qint64 seqDumpPos;
+    qint64 *pPos;
+    qint64 *pDevicePos;
     bool baseReadLineDataCalled;
+    bool firstRead;
 
     virtual bool putCharHelper(char c);