1
/***************************************************************************
2
* Copyright (C) 2008-2009 by Valerio Pilo *
5
* This program is free software; you can redistribute it and/or modify *
6
* it under the terms of the GNU Lesser General Public License as *
7
* published by the Free Software Foundation; either version 2.1 of the *
8
* License, or (at your option) any later version. *
10
* This program is distributed in the hope that it will be useful, *
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13
* GNU General Public License for more details. *
15
* You should have received a copy of the GNU Lesser General Public *
16
* License along with this program; if not, write to the *
17
* Free Software Foundation, Inc., *
18
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19
***************************************************************************/
21
#include "isfqt-internal.h"
22
#include "bitpacking.h"
29
using namespace Isf::Compress;
34
* Get the most appropriate block size for the given data.
36
* @param data Data to analyze
39
quint8 BitPackingAlgorithm::blockSize( const QList<qint64> &data )
44
for( qint32 index = 0; index < data.size(); ++index )
50
// We need the positive numbers: the +1 is for the sign bit
54
// Shift right the value by blockSize bits until it becomes zero:
55
// we need to detect the maximum bitwise size required to store
56
// the numbers in the data array.
65
// The sign bit always takes up a bit
74
* Compress data with the Bit Packing algorithm.
76
* @param encodedData Byte array where to store the compressed data
77
* @param blockSize Block size to use for compression
78
* @param source List of values to compress
81
bool BitPackingAlgorithm::deflate( QByteArray &encodedData, quint8 blockSize, const QList<qint64> &source )
85
qWarning() << "A block size of" << blockSize << "is too high!";
86
blockSize = 64; // Fuck it :P
89
quint8 blockSizeLeft; // Remaining bits to encode of the current value
90
quint8 freeBits = 8; // Free bits of the current byte, in LSB order
91
quint8 signMask = 1 << ( blockSize - 1 ); // Mask to add the sign bit
93
quint8 byte = 0; // Byte to add to the array
96
for( qint64 index = 0; index < source.count(); ++index )
98
currentValue = source[ index ];
100
if( currentValue < 0 )
102
currentValue |= signMask;
105
blockSizeLeft = blockSize;
107
if( freeBits >= blockSizeLeft )
109
freeBits -= blockSizeLeft;
110
byte |= currentValue << freeBits;
112
encodedData.append( byte );
119
// Fill the current byte
120
quint64 mask = 0xFFFFFFFF >> ( 32 - blockSizeLeft );
121
byte |= currentValue >> ( blockSizeLeft - freeBits );
123
encodedData.append( byte );
126
blockSizeLeft -= freeBits;
128
currentValue &= mask;
130
// Then fill all the next bytes required to encode the current value,
131
// except the last one
132
while( blockSizeLeft > 8 )
135
encodedData.append( currentValue >> blockSizeLeft );
138
currentValue &= mask;
141
// Finally, add the last byte
142
freeBits = 8 - blockSizeLeft;
143
encodedData.append( currentValue << freeBits );
153
* Decompress data with the Bit Packing algorithm.
155
* @param source Data source where to read the compressed bytes
156
* @param length Number of items to read
157
* @param blockSize Block size to use for compression
158
* @param decodedData List where to place decompressed values
161
bool BitPackingAlgorithm::inflate( DataSource &source, quint64 length, quint8 blockSize, QList<qint64> &decodedData )
165
qWarning() << "A block size of" << blockSize << "is too high!";
166
blockSize = 64; // Fuck it :P
171
qWarning() << "Cannot inflate: no more bits available!";
177
quint64 signMask = (quint64)( 0xFFFFFFFF * pow( 2, blockSize - 1 ) ) & 0xFFFFFFFF;
179
while( index++ < length )
181
value = source.getBits( blockSize );
183
// If the mask matches, the sign bit is set, so ORing value and mask will
184
// set all leftmost bits to 1, making it a real 64bit signed integer
185
if( value & signMask )
190
decodedData.append( value );