Warning, file /office/calligra/libs/store/KoXmlVector.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /* This file is part of the KDE project
0002    Copyright (C) 2005-2006 Ariya Hidayat <ariya@kde.org>
0003 
0004    This library is free software; you can redistribute it and/or
0005    modify it under the terms of the GNU Library General Public
0006    License as published by the Free Software Foundation; either
0007    version 2 of the License, or (at your option) any later version.
0008 
0009    This library is distributed in the hope that it will be useful,
0010    but WITHOUT ANY WARRANTY; without even the implied warranty of
0011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0012    Library General Public License for more details.
0013 
0014    You should have received a copy of the GNU Library General Public License
0015    along with this library; see the file COPYING.LIB.  If not, write to
0016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0017    Boston, MA 02110-1301, USA.
0018 */
0019 
0020 #ifndef KO_XMLVECTOR_H
0021 #define KO_XMLVECTOR_H
0022 
0023 // comment it to test this class without the compression
0024 #define KOXMLVECTOR_USE_LZF
0025 
0026 #ifdef KOXMLVECTOR_USE_LZF
0027 #include "KoLZF.h"
0028 #endif
0029 
0030 #include <QVector>
0031 #include <QByteArray>
0032 #include <QDataStream>
0033 #include <QBuffer>
0034 
0035 /**
0036  * KoXmlVector
0037  *
0038  * similar to QVector, but using LZF compression to save memory space
0039  * this class is however not reentrant
0040  *
0041  * Needs to be used like this, otherwise will crash:
0042  * <ul>
0043  * <li>add content with newItem()</li>
0044  * <li>finish adding content with squeeze()</li>
0045  * <li>just read content with operator[]</li>
0046  * </ul>
0047  *
0048  * @param uncompressedItemCount when number of buffered items reach this,
0049  *      compression will start small value will give better memory usage at the
0050  *      cost of speed bigger value will be better in term of speed, but use
0051  *      more memory
0052  */
0053 template <typename T, int uncompressedItemCount = 256, int reservedBufferSize = 1024*1024>
0054 class KoXmlVector
0055 {
0056 private:
0057     unsigned m_totalItems;
0058     QVector<unsigned> m_startIndex;
0059     QVector<QByteArray> m_blocks;
0060 
0061     mutable unsigned m_bufferStartIndex;
0062     mutable QVector<T> m_bufferItems;
0063     mutable QByteArray m_bufferData;
0064 
0065 protected:
0066     /**
0067      * fetch given item index to the buffer
0068      * will INVALIDATE all references to the buffer
0069      */
0070     void fetchItem(unsigned index) const {
0071         // already in the buffer ?
0072         if (index >= m_bufferStartIndex)
0073             if (index - m_bufferStartIndex < (unsigned)m_bufferItems.count())
0074                 return;
0075 
0076         // search in the stored blocks
0077         // TODO: binary search to speed up
0078         int loc = m_startIndex.count() - 1;
0079         for (int c = 0; c < m_startIndex.count() - 1; ++c)
0080             if (index >= m_startIndex[c])
0081                 if (index < m_startIndex[c+1]) {
0082                     loc = c;
0083                     break;
0084                 }
0085 
0086         m_bufferStartIndex = m_startIndex[loc];
0087 #ifdef KOXMLVECTOR_USE_LZF
0088         KoLZF::decompress(m_blocks[loc], m_bufferData);
0089 #else
0090         m_bufferData = m_blocks[loc];
0091 #endif
0092         QBuffer buffer(&m_bufferData);
0093         buffer.open(QIODevice::ReadOnly);
0094         QDataStream in(&buffer);
0095         m_bufferItems.clear();
0096         in >> m_bufferItems;
0097     }
0098 
0099     /**
0100      * store data in the buffer to main m_blocks
0101      */
0102     void storeBuffer() {
0103         QBuffer buffer;
0104         buffer.open(QIODevice::WriteOnly);
0105         QDataStream out(&buffer);
0106         out << m_bufferItems;
0107 
0108         m_startIndex.append(m_bufferStartIndex);
0109 #ifdef KOXMLVECTOR_USE_LZF
0110         m_blocks.append(KoLZF::compress(buffer.data()));
0111 #else
0112         m_blocks.append(buffer.data());
0113 #endif
0114 
0115         m_bufferStartIndex += m_bufferItems.count();
0116         m_bufferItems.clear();
0117     }
0118 
0119 public:
0120     inline KoXmlVector(): m_totalItems(0), m_bufferStartIndex(0) {};
0121 
0122     void clear() {
0123         m_totalItems = 0;
0124         m_startIndex.clear();
0125         m_blocks.clear();
0126 
0127         m_bufferStartIndex = 0;
0128         m_bufferItems.clear();
0129         m_bufferData.reserve(reservedBufferSize);
0130     }
0131 
0132     inline int count() const {
0133         return (int)m_totalItems;
0134     }
0135     inline int size() const {
0136         return (int)m_totalItems;
0137     }
0138     inline bool isEmpty() const {
0139         return m_totalItems == 0;
0140     }
0141 
0142     /**
0143      * append a new item
0144      * WARNING: use the return value as soon as possible
0145      * it may be invalid if another function is invoked
0146      */
0147     T& newItem() {
0148         // buffer full?
0149         if (m_bufferItems.count() >= uncompressedItemCount - 1)
0150             storeBuffer();
0151 
0152         ++m_totalItems;
0153         m_bufferItems.resize(m_bufferItems.count() + 1);
0154         return m_bufferItems[m_bufferItems.count()-1];
0155     }
0156 
0157     /**
0158      * WARNING: use the return value as soon as possible
0159      * it may be invalid if another function is invoked
0160      */
0161     const T &operator[](int i) const {
0162         fetchItem((unsigned)i);
0163         return m_bufferItems[i - m_bufferStartIndex];
0164     }
0165 
0166     /**
0167      * optimize memory usage
0168      * will INVALIDATE all references to the buffer
0169      */
0170     void squeeze() {
0171         storeBuffer();
0172     }
0173 
0174 };
0175 
0176 #endif