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