[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    koffice/filters/kspread/excel
From:       Marijn Kruisselbrink <m.kruisselbrink () student ! tue ! nl>
Date:       2010-08-29 20:53:59
Message-ID: 20100829205359.ACC28AC883 () svn ! kde ! org
[Download RAW message or body]

SVN commit 1169647 by mkruisselbrink:

make CFBWriter's streams be random access; writing xls files needs random access \
streams to update previously written records

 M  +61 -1     export/CFBWriter.cpp  
 M  +2 -0      export/CFBWriter.h  
 M  +20 -0     sidewinder/XlsRecordOutputStream.cpp  
 M  +11 -0     sidewinder/XlsRecordOutputStream.h  


--- trunk/koffice/filters/kspread/excel/export/CFBWriter.cpp #1169646:1169647
@@ -80,9 +80,12 @@
     virtual ~StreamIODevice();
     virtual void close();
     virtual bool open(OpenMode mode);
+    virtual qint64 size() const;
 protected:
     virtual qint64 writeData(const char *data, qint64 len);
     virtual qint64 readData(char *data, qint64 maxlen);
+    void appendData(const char *data, qint64 len);
+    qint64 internalWriteData(const char* data, qint64 len, qint64 pos);
 private:
     DirectoryEntry& m_entry;
     CFBWriter& m_writer;
@@ -133,8 +136,13 @@
     return false;
 }
 
-qint64 CFBWriter::StreamIODevice::writeData(const char *data, qint64 len)
+qint64 CFBWriter::StreamIODevice::size() const
 {
+    return m_entry.streamSize + m_buffer.size();
+}
+
+void CFBWriter::StreamIODevice::appendData(const char *data, qint64 len)
+{
     m_buffer.append(data, len);
     while (m_buffer.size() > 4096) {
         QByteArray sector = m_buffer.left(4096);
@@ -145,9 +153,48 @@
         }
         m_entry.streamSize += 4096;
     }
+}
+
+qint64 CFBWriter::StreamIODevice::writeData(const char *data, qint64 len)
+{
+    qint64 bytesWritten = 0;
+    qint64 curPos = pos();
+    while (bytesWritten < len) {
+        bytesWritten += internalWriteData(data + bytesWritten, len - bytesWritten, \
curPos + bytesWritten); +    }
     return len;
 }
 
+qint64 CFBWriter::StreamIODevice::internalWriteData(const char *data, qint64 len, \
qint64 pos) +{
+    Q_ASSERT(pos >= 0 && pos <= size());
+    if (pos == size()) {
+        appendData(data, len);
+        return len;
+    } else {
+        if (pos + len > size()) {
+            len = size() - pos;
+        }
+        qint64 bufferStart = m_entry.streamSize;
+        if (pos < bufferStart) {
+            unsigned sectorIndex = pos/4096;
+            unsigned sector = m_entry.firstSector;
+            while (sectorIndex--) {
+                sector = m_writer.m_fat[sector];
+            }
+            unsigned sectorOffset = pos%4096;
+            if (sectorOffset + len > 4096) {
+                len = 4096 - sectorOffset;
+            }
+            m_writer.writeData(sector, sectorOffset, QByteArray::fromRawData(data, \
len)); +        } else {
+            // len has already been adjusted to be fully inside the buffer, so just \
overwrite what is in the buffer with the subset of data we have +            \
m_buffer.replace(pos - bufferStart, len, QByteArray::fromRawData(data, len)); +       \
} +        return len;
+    }
+}
+
 qint64 CFBWriter::StreamIODevice::readData(char *data, qint64 maxlen)
 {
     Q_UNUSED(data);
@@ -337,6 +384,19 @@
     m_miniFatDataStream = new StreamIODevice(*this, m_entries[0]);
 }
 
+void CFBWriter::writeData(unsigned sector, unsigned sectorOffset, const QByteArray \
&data) +{
+    Q_ASSERT(m_device);
+    Q_ASSERT(m_device->isOpen());
+    Q_ASSERT(m_device->isWritable());
+    Q_ASSERT(!m_device->isSequential());
+    Q_ASSERT(sector < unsigned(m_fat.size()));
+    Q_ASSERT(sectorOffset + data.length() <= 4096);
+
+    m_device->seek((sector + 1) * 4096 + sectorOffset);
+    m_device->write(data);
+}
+
 unsigned CFBWriter::writeSector(const QByteArray &data, unsigned previousSector)
 {
     Q_ASSERT(m_device);
--- trunk/koffice/filters/kspread/excel/export/CFBWriter.h #1169646:1169647
@@ -48,6 +48,8 @@
 
     unsigned writeMiniSector(const QByteArray& data, unsigned previousSector = -1);
 
+    void writeData(unsigned sector, unsigned sectorOffset, const QByteArray& data);
+
     unsigned fatSectorCount() const;
 
     QList<unsigned> m_difat;
--- trunk/koffice/filters/kspread/excel/sidewinder/XlsRecordOutputStream.cpp \
#1169646:1169647 @@ -32,9 +32,15 @@
 {
     Q_ASSERT(device->isOpen());
     Q_ASSERT(device->isWritable());
+    Q_ASSERT(!device->isSequential());
     m_dataStream.setByteOrder(QDataStream::LittleEndian);
 }
 
+qint64 XlsRecordOutputStream::pos() const
+{
+    return m_dataStream.device()->pos();
+}
+
 void XlsRecordOutputStream::writeRecord(const Record& record)
 {
     startRecord(record.rtti());
@@ -42,6 +48,20 @@
     endRecord();
 }
 
+void XlsRecordOutputStream::writeRecord(Record& record)
+{
+    record.setPosition(pos());
+    writeRecord(const_cast<const Record&>(record));
+}
+
+void XlsRecordOutputStream::rewriteRecord(const Record& record)
+{
+    qint64 oldPos = pos();
+    m_dataStream.device()->seek(record.position());
+    writeRecord(record);
+    m_dataStream.device()->seek(oldPos);
+}
+
 void XlsRecordOutputStream::startRecord(unsigned recordType)
 {
     Q_ASSERT(m_currentRecord == NORECORD);
--- trunk/koffice/filters/kspread/excel/sidewinder/XlsRecordOutputStream.h \
#1169646:1169647 @@ -34,7 +34,16 @@
 public:
     XlsRecordOutputStream(QIODevice* device);
 
+    /**
+     * Writes a record, updates the records position to the position it is saved to \
in the file. +     */
+    void writeRecord(Record& record);
     void writeRecord(const Record& record);
+    /**
+     * Rewrites the given record at its recordPosition by first seeking there, and \
then going back to where the output device was first. +     */
+    void rewriteRecord(const Record& record);
+
     void startRecord(unsigned recordType);
     void endRecord();
 
@@ -44,6 +53,8 @@
     void writeUnicodeStringWithFlags(const QString& value);
     void writeByteString(const QString& value);
     void writeBlob(const QByteArray& value);
+
+    qint64 pos() const;
 private:
     QDataStream m_dataStream;
     unsigned m_currentRecord;


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic