Upstream tarball 20080414
[amule.git] / src / RLE.cpp
blob53bd3e2781186801526e9de7ccce6d4bcad3ac7b
1 //
2 // This file is part of the aMule Project.
3 //
4 // Copyright (c) 2003-2008 aMule Team ( admin@amule.org / http://www.amule.org )
5 //
6 // Any parts of this program derived from the xMule, lMule or eMule project,
7 // or contributed by third-party developers are copyrighted by their
8 // respective authors.
9 //
10 // This program is free software; you can redistribute it and/or modify
11 // it under the terms of the GNU General Public License as published by
12 // the Free Software Foundation; either version 2 of the License, or
13 // (at your option) any later version.
15 // This program is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with this program; if not, write to the Free Software
22 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #include "RLE.h"
26 #include "ArchSpecific.h"
30 * RLE encoder implementation. This is RLE implementation for very specific
31 * purpose: encode DIFFERENCE between subsequent states of status bar.
33 * This difference is calculated by xor-ing with previous data
35 * We can't use implementation with "control char" since this encoder
36 * will process binary data - not ascii (or unicode) strings
38 RLE_Data::RLE_Data(int len, bool use_diff)
40 m_len = len;
41 m_use_diff = use_diff;
43 m_buff = new unsigned char[m_len];
44 memset(m_buff, 0, m_len);
46 // in worst case 2-byte sequence encoded as 3. So, data can grow at 1/3
47 m_enc_buff = new unsigned char[m_len*4/3 + 1];
50 RLE_Data::RLE_Data()
52 m_buff = 0;
53 m_enc_buff = 0;
54 m_len = 0;
55 m_use_diff = 0;
58 RLE_Data::RLE_Data(const RLE_Data &obj)
60 m_len = obj.m_len;
61 m_use_diff = obj.m_use_diff;
63 m_buff = new unsigned char[m_len];
64 memcpy(m_buff, obj.m_buff, m_len);
66 m_enc_buff = new unsigned char[m_len*4/3 + 1];
69 RLE_Data &RLE_Data::operator=(const RLE_Data &obj)
71 m_len = obj.m_len;
73 m_use_diff = obj.m_use_diff;
75 m_buff = new unsigned char[m_len];
76 memcpy(m_buff, obj.m_buff, m_len);
78 m_enc_buff = new unsigned char[m_len*4/3 + 1];
80 return *this;
83 RLE_Data::~RLE_Data()
85 if ( m_buff ) {
86 delete [] m_buff;
88 if ( m_enc_buff ) {
89 delete [] m_enc_buff;
93 void RLE_Data::Realloc(int size)
95 if ( size == m_len ) {
96 return;
99 unsigned char *buff = new unsigned char[size];
100 if ( size > m_len ) {
101 memset(buff + m_len, 0, size - m_len);
102 memcpy(buff, m_buff, m_len);
103 } else {
104 memcpy(buff, m_buff, size);
106 delete [] m_buff;
107 m_buff = buff;
109 buff = new unsigned char[size*4/3 + 1];
110 if ( size > m_len ) {
111 memset(buff + m_len*4/3 + 1, 0, (size - m_len)*4/3);
112 memcpy(buff, m_enc_buff, m_len*4/3 + 1);
113 } else {
114 memcpy(buff, m_enc_buff, size*4/3 + 1);
116 delete [] m_enc_buff;
117 m_enc_buff = buff;
119 m_len = size;
122 const unsigned char *RLE_Data::Decode(const unsigned char *buff, int len)
125 // Open RLE
128 int i = 0, j = 0;
129 while ( j != m_len ) {
131 if ( i < (len -1) ) {
132 if (buff[i+1] == buff[i]) {
133 // this is sequence
134 memset(m_enc_buff + j, buff[i], buff[i + 2]);
135 j += buff[i + 2];
136 i += 3;
137 } else {
138 // this is single byte
139 m_enc_buff[j++] = buff[i++];
141 } else {
142 // only 1 byte left in encoded data - it can't be sequence
143 m_enc_buff[j++] = buff[i++];
144 // if there's no more data, but buffer end is not reached,
145 // it must be error in some point
146 if ( j != m_len ) {
147 printf("RLE_Data: decoding error. %d bytes decoded to %d instead of %d\n", len, j, m_len);
149 break;
153 // Recreate data from diff
155 if ( m_use_diff ) {
156 for (int k = 0; k < m_len; k++) {
157 m_buff[k] ^= m_enc_buff[k];
161 return m_buff;
164 void PartFileEncoderData::Decode(unsigned char *gapdata, int gaplen, unsigned char *partdata, int partlen)
166 m_part_status.Decode(partdata, partlen);
168 // in a first dword - real size
169 uint32 gapsize = ENDIAN_NTOHL( RawPeekUInt32( gapdata ) );
170 gapdata += sizeof(uint32);
171 m_gap_status.Realloc(gapsize*2*sizeof(uint64));
173 m_gap_status.Decode(gapdata, gaplen - sizeof(uint32));
176 unsigned char RLE_Data_BV::m_buff[256];
178 RLE_Data_BV::RLE_Data_BV(int len) : m_last_buff(len)
182 int RLE_Data_BV::Encode(std::vector<bool> &data)
184 unsigned char *curr = m_buff;
185 std::vector<bool>::const_iterator i = data.begin();
186 std::vector<bool>::const_iterator j = m_last_buff.begin();
187 while( i != data.end() ) {
188 unsigned char count = 0;
189 while ( (i != data.end()) && ( (*i ^ *j) == false) ) {
190 count++;
191 i++;
192 j++;
194 *curr++ = count;
196 m_last_buff = data;
197 return 0;
200 // File_checked_for_headers